|
@@ -1,816 +0,0 @@
|
|
|
-//
|
|
|
-// KMSearchReplaceWindowController.swift
|
|
|
-// PDF Reader Pro
|
|
|
-//
|
|
|
-// Created by User-Tangchao on 2024/8/7.
|
|
|
-//
|
|
|
-
|
|
|
-import Cocoa
|
|
|
-import KMComponentLibrary
|
|
|
-
|
|
|
-class KMSearchReplaceWindowController_Window: NSWindow {
|
|
|
- override var canBecomeMain: Bool {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- override var canBecomeKey: Bool {
|
|
|
- return true
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@objc enum KMSearchReplaceType: Int {
|
|
|
- case none = 0
|
|
|
- case search = 1
|
|
|
- case replace = 2
|
|
|
-}
|
|
|
-
|
|
|
-class KMNSearchReplaceTitleBarView: NSView {
|
|
|
- private lazy var closeButton_: ComponentButton = {
|
|
|
- let view = ComponentButton()
|
|
|
- let prop = ComponentButtonProperty()
|
|
|
- prop.type = .text_gray
|
|
|
- prop.size = .xxs
|
|
|
- prop.onlyIcon = true
|
|
|
- prop.icon = NSImage(named: "KMImageNameSearchReplaceClose")
|
|
|
- view.properties = prop
|
|
|
- view.setTarget(self, action: #selector(closeAction))
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- private lazy var switchButton_: ComponentButton = {
|
|
|
- let view = ComponentButton()
|
|
|
- let prop = ComponentButtonProperty()
|
|
|
- prop.type = .text_gray
|
|
|
- prop.size = .xxs
|
|
|
- prop.onlyIcon = true
|
|
|
- prop.icon = NSImage(named: "KMImageNameSearchReplaceSwitch")
|
|
|
- view.properties = prop
|
|
|
- view.setTarget(self, action: #selector(switchAction))
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- private lazy var titleLabel_: NSTextField = {
|
|
|
- let view = NSTextField(labelWithString: "")
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- var titleLabel: NSTextField {
|
|
|
- get {
|
|
|
- return titleLabel_
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- var itemClick: KMCommonClickBlock?
|
|
|
-
|
|
|
- convenience init() {
|
|
|
- self.init(frame: .init(x: 0, y: 0, width: 300, height: 44))
|
|
|
- }
|
|
|
-
|
|
|
- override func awakeFromNib() {
|
|
|
- super.awakeFromNib()
|
|
|
-
|
|
|
- initSubviews()
|
|
|
- }
|
|
|
-
|
|
|
- override init(frame frameRect: NSRect) {
|
|
|
- super.init(frame: frameRect)
|
|
|
-
|
|
|
- initSubviews()
|
|
|
- }
|
|
|
-
|
|
|
- required init?(coder: NSCoder) {
|
|
|
- super.init(coder: coder)
|
|
|
-
|
|
|
- initSubviews()
|
|
|
- }
|
|
|
-
|
|
|
- func initSubviews() {
|
|
|
- addSubview(closeButton_)
|
|
|
- addSubview(switchButton_)
|
|
|
- addSubview(titleLabel_)
|
|
|
-
|
|
|
- closeButton_.km_add_size_constraint(size: .init(width: 24, height: 24))
|
|
|
- closeButton_.km_add_top_constraint(constant: 8)
|
|
|
- closeButton_.km_add_trailing_constraint(constant: -8)
|
|
|
-
|
|
|
- switchButton_.km_add_size_constraint(size: .init(width: 24, height: 24))
|
|
|
- switchButton_.km_add_top_constraint(constant: 8)
|
|
|
- switchButton_.km_add_trailing_constraint(equalTo: closeButton_, attribute: .leading, constant: -8)
|
|
|
-
|
|
|
- titleLabel_.km_add_leading_constraint(constant: 24)
|
|
|
- titleLabel_.km_add_top_constraint(constant: 24)
|
|
|
- }
|
|
|
-
|
|
|
- @objc func closeAction() {
|
|
|
- itemClick?(1)
|
|
|
- }
|
|
|
-
|
|
|
- @objc func switchAction() {
|
|
|
- itemClick?(2)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class KMNSearchReplaceSearchItemView: NSView {
|
|
|
- private lazy var previousButton_: ComponentButton = {
|
|
|
- let view = ComponentButton()
|
|
|
- view.properties = ComponentButtonProperty(type: .gray, size: .s, 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: .gray, size: .s, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchNext"))
|
|
|
-// view.setTarget(self, action: #selector(nextActon))
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- private lazy var input_: ComponentInput = {
|
|
|
- let view = ComponentInput()
|
|
|
- let prop = ComponentInputProperty()
|
|
|
- prop.size = .s
|
|
|
- prop.showPrefix = true
|
|
|
- prop.showSuffix = true
|
|
|
- view.properties = prop
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- convenience init() {
|
|
|
- self.init(frame: .init(x: 0, y: 0, width: 300, height: 44))
|
|
|
- }
|
|
|
-
|
|
|
- override func awakeFromNib() {
|
|
|
- super.awakeFromNib()
|
|
|
-
|
|
|
- initSubviews()
|
|
|
- }
|
|
|
-
|
|
|
- override init(frame frameRect: NSRect) {
|
|
|
- super.init(frame: frameRect)
|
|
|
-
|
|
|
- initSubviews()
|
|
|
- }
|
|
|
-
|
|
|
- required init?(coder: NSCoder) {
|
|
|
- super.init(coder: coder)
|
|
|
-
|
|
|
- initSubviews()
|
|
|
- }
|
|
|
-
|
|
|
- func initSubviews() {
|
|
|
- addSubview(nextButton_)
|
|
|
- addSubview(previousButton_)
|
|
|
- addSubview(input_)
|
|
|
-
|
|
|
- nextButton_.km_add_size_constraint(size: .init(width: 32, height: 32))
|
|
|
- nextButton_.km_add_top_constraint(constant: 0)
|
|
|
- nextButton_.km_add_trailing_constraint(constant: -24)
|
|
|
-
|
|
|
- previousButton_.km_add_size_constraint(size: .init(width: 32, height: 32))
|
|
|
- previousButton_.km_add_top_constraint(constant: 0)
|
|
|
- previousButton_.km_add_trailing_constraint(equalTo: nextButton_, attribute: .leading, constant: -8)
|
|
|
-
|
|
|
- input_.km_add_top_constraint(constant: 0)
|
|
|
- input_.km_add_leading_constraint(constant: 24)
|
|
|
- input_.km_add_height_constraint(constant: 32)
|
|
|
- input_.km_add_trailing_constraint(equalTo: previousButton_, attribute: .leading, constant: -8)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class KMSearchReplaceWindowController: KMNBaseWindowController {
|
|
|
- @IBOutlet weak var titleBarBox: NSBox!
|
|
|
- @IBOutlet weak var closeButton: NSButton!
|
|
|
-
|
|
|
- @IBOutlet weak var tabBox: NSBox!
|
|
|
- @IBOutlet weak var searchTabButton: NSButton!
|
|
|
- @IBOutlet weak var replaceTabButton: NSButton!
|
|
|
- @IBOutlet weak var tabBottomLine: NSBox!
|
|
|
- @IBOutlet weak var tabSelectedLine: NSBox!
|
|
|
- @IBOutlet weak var tabSelectedLineLeftConst: NSLayoutConstraint!
|
|
|
-
|
|
|
- @IBOutlet weak var searchBox: NSBox!
|
|
|
- @IBOutlet weak var searchTitleLabel: NSTextField!
|
|
|
- @IBOutlet weak var searchInputBox: NSBox!
|
|
|
- @IBOutlet weak var searchInputView: NSTextField!
|
|
|
- @IBOutlet weak var matchWholeCheck: NSButton!
|
|
|
- @IBOutlet weak var caseSensitiveCheck: NSButton!
|
|
|
- @IBOutlet weak var previousButton: NSButton!
|
|
|
- @IBOutlet weak var nextButton: NSButton!
|
|
|
-
|
|
|
- @IBOutlet weak var replaceBox: NSBox!
|
|
|
- @IBOutlet weak var replaceTitleLabel: NSTextField!
|
|
|
- @IBOutlet weak var replaceInputBox: NSBox!
|
|
|
- @IBOutlet weak var replaceInputView: NSTextField!
|
|
|
-
|
|
|
- @IBOutlet weak var bottomBarBox: NSBox!
|
|
|
- @IBOutlet weak var replaceButton: NSButton!
|
|
|
- @IBOutlet weak var replaceAllButton: NSButton!
|
|
|
-
|
|
|
- var replaceCallback: (() -> Void)?
|
|
|
- var itemClick: KMCommonClickBlock?
|
|
|
-
|
|
|
- private var _modalSession: NSApplication.ModalSession?
|
|
|
-
|
|
|
- private var handdler: KMSearchReplaceHanddler = KMSearchReplaceHanddler()
|
|
|
- private var type_: KMSearchReplaceType = .search
|
|
|
-
|
|
|
- private var currentSel: CPDFSelection?
|
|
|
-
|
|
|
- private var finding_ = false
|
|
|
-
|
|
|
- private lazy var titleBarView_: KMNSearchReplaceTitleBarView = {
|
|
|
- let view = KMNSearchReplaceTitleBarView()
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- private lazy var searchItemView_: KMNSearchReplaceSearchItemView = {
|
|
|
- let view = KMNSearchReplaceSearchItemView()
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- private lazy var replaceItemView_: KMNSearchReplacePopItemView = {
|
|
|
- let view = KMNSearchReplacePopItemView()
|
|
|
- return view
|
|
|
- }()
|
|
|
-
|
|
|
- deinit {
|
|
|
- KMPrint("KMSearchReplaceWindowController deinit.")
|
|
|
-
|
|
|
- DistributedNotificationCenter.default().removeObserver(self)
|
|
|
- }
|
|
|
-
|
|
|
- convenience init(with pdfView: CPDFView?, type: KMSearchReplaceType) {
|
|
|
- self.init(windowNibName: "KMSearchReplaceWindowController")
|
|
|
-
|
|
|
- self.handdler.pdfView = pdfView
|
|
|
- self.type_ = type
|
|
|
- }
|
|
|
-
|
|
|
- override func windowDidLoad() {
|
|
|
- super.windowDidLoad()
|
|
|
-
|
|
|
- self.initDefaultValue()
|
|
|
- self.switchType(self.type_)
|
|
|
- self.updateViewColor()
|
|
|
- DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChanged), name: NSApplication.interfaceThemeChangedNotification, object: nil)
|
|
|
- }
|
|
|
-
|
|
|
- func initDefaultValue() {
|
|
|
- self.window?.isMovableByWindowBackground = true
|
|
|
-
|
|
|
- self.window?.contentView?.wantsLayer = true
|
|
|
- self.window?.contentView?.layer?.cornerRadius = 4
|
|
|
- self.window?.contentView?.layer?.masksToBounds = true
|
|
|
-
|
|
|
- self.window?.backgroundColor = .clear
|
|
|
-
|
|
|
- self.titleBarBox.boxType = .custom
|
|
|
- self.titleBarBox.borderWidth = 0
|
|
|
- self.closeButton.imagePosition = .imageOnly
|
|
|
- self.closeButton.image = NSImage(named: "KMImageNameUXIconBtnCloseNor")
|
|
|
- self.closeButton.target = self
|
|
|
- self.closeButton.action = #selector(_closeAction)
|
|
|
- self.titleBarBox.contentView = titleBarView_
|
|
|
- titleBarView_.titleLabel.font = .SFProTextRegularFont(14)
|
|
|
- titleBarView_.itemClick = { [unowned self] idx, _ in
|
|
|
- if idx == 1 {
|
|
|
- self._closeAction(NSButton())
|
|
|
- } else if idx == 2 {
|
|
|
- self._closeAction(NSButton())
|
|
|
-
|
|
|
- self.itemClick?(1)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- self.searchTabButton.target = self
|
|
|
- self.searchTabButton.action = #selector(_searchTabAction)
|
|
|
- self.searchTabButton.title = " \(NSLocalizedString("Search", comment: ""))"
|
|
|
- self.searchTabButton.image = NSImage(named: "KMImageNameSearchIcon")
|
|
|
- self.searchTabButton.imagePosition = .imageLeft
|
|
|
-// self.searchTabButton.imageHugsTitle = true
|
|
|
-
|
|
|
- searchBox.contentView = searchItemView_
|
|
|
-
|
|
|
- self.replaceTabButton.target = self
|
|
|
- self.replaceTabButton.action = #selector(_replaceTabAction)
|
|
|
- self.replaceTabButton.title = " \(NSLocalizedString("Replace", comment: ""))"
|
|
|
- self.replaceTabButton.image = NSImage(named: "KMImageNameReplaceIcon")
|
|
|
- self.replaceTabButton.imagePosition = .imageLeft
|
|
|
- self.tabSelectedLine.borderWidth = 0
|
|
|
- self.tabSelectedLine.fillColor = NSColor(hex: "#4982E6")
|
|
|
-
|
|
|
- self.searchBox.borderWidth = 0
|
|
|
- // #0E1114
|
|
|
- self.searchTitleLabel.stringValue = NSLocalizedString("Search", comment: "")
|
|
|
- self.searchTitleLabel.font = NSFont.SFProTextBoldFont(14)
|
|
|
- self.searchInputBox.cornerRadius = 0
|
|
|
- self.searchInputView.drawsBackground = false
|
|
|
- self.searchInputView.isBordered = false
|
|
|
- self.searchInputView.delegate = self
|
|
|
-
|
|
|
- self.matchWholeCheck.title = NSLocalizedString("Whole Words Only", comment: "")
|
|
|
- self.matchWholeCheck.target = self
|
|
|
- self.matchWholeCheck.action = #selector(_checkAction)
|
|
|
- self.matchWholeCheck.state = .off
|
|
|
- self.caseSensitiveCheck.title = NSLocalizedString("Ignore Case", comment: "")
|
|
|
- self.caseSensitiveCheck.target = self
|
|
|
- self.caseSensitiveCheck.action = #selector(_checkAction)
|
|
|
- self.caseSensitiveCheck.state = .off
|
|
|
- self.previousButton.title = NSLocalizedString("Next", comment: "")
|
|
|
- self.previousButton.target = self
|
|
|
- self.previousButton.action = #selector(_nextAction)
|
|
|
- self.nextButton.title = NSLocalizedString("Previous", comment: "")
|
|
|
- self.nextButton.target = self
|
|
|
- self.nextButton.action = #selector(_previousAction)
|
|
|
-
|
|
|
- self.replaceBox.borderWidth = 0
|
|
|
- self.replaceTitleLabel.stringValue = NSLocalizedString("Replace with", comment: "")
|
|
|
- self.replaceTitleLabel.font = NSFont.SFProTextBoldFont(14)
|
|
|
- self.replaceInputBox.cornerRadius = 0
|
|
|
- self.replaceInputView.drawsBackground = false
|
|
|
- self.replaceInputView.isBordered = false
|
|
|
- self.replaceInputView.delegate = self
|
|
|
-
|
|
|
- replaceBox.contentView = replaceItemView_
|
|
|
-
|
|
|
- self.bottomBarBox.borderWidth = 0
|
|
|
- self.replaceButton.title = NSLocalizedString("Replace", comment: "")
|
|
|
- self.replaceButton.target = self
|
|
|
- self.replaceButton.action = #selector(_replaceAction)
|
|
|
- self.replaceAllButton.title = NSLocalizedString("Replace All", comment: "")
|
|
|
- self.replaceAllButton.target = self
|
|
|
- self.replaceAllButton.action = #selector(_replaceAllAction)
|
|
|
-
|
|
|
- if self.searchInputView.stringValue.isEmpty {
|
|
|
- self.previousButton.isEnabled = false
|
|
|
- self.nextButton.isEnabled = false
|
|
|
- self.replaceButton.isEnabled = false
|
|
|
- self.replaceAllButton.isEnabled = false
|
|
|
- } else {
|
|
|
- self.previousButton.isEnabled = true
|
|
|
- self.nextButton.isEnabled = true
|
|
|
- self.replaceButton.isEnabled = true
|
|
|
- self.replaceAllButton.isEnabled = true
|
|
|
-
|
|
|
- self.currentSel = nil
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- override func updateUILanguage() {
|
|
|
- super.updateUILanguage()
|
|
|
-
|
|
|
- KMMainThreadExecute {
|
|
|
- self.titleBarView_.titleLabel.stringValue = KMLocalizedString("Search")
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- override func updateUIThemeColor() {
|
|
|
- super.updateUIThemeColor()
|
|
|
-
|
|
|
- KMMainThreadExecute {
|
|
|
- self.titleBarView_.titleLabel.textColor = KMNColorTools.colorText_1()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // MARK: - Actions
|
|
|
-
|
|
|
- @objc private func _closeAction(_ sender: NSButton) {
|
|
|
- self.endModal(sender)
|
|
|
-
|
|
|
- self.handdler.clearData()
|
|
|
- }
|
|
|
-
|
|
|
- @objc private func _previousAction(_ sender: NSButton) {
|
|
|
- let isEditing = self.handdler.pdfView?.isEditing() ?? false
|
|
|
- if isEditing == false {
|
|
|
- guard let model = self.handdler.searchResults.safe_element(for: self.handdler.showIdx-1) as? KMSearchMode else {
|
|
|
- return
|
|
|
- }
|
|
|
- self.handdler.showIdx -= 1
|
|
|
- self.handdler.showSelection(model.selection)
|
|
|
- } else {
|
|
|
- if let _ = self.currentSel {
|
|
|
- self.currentSel = self.handdler.pdfView?.document.findForwardEditText()
|
|
|
- if let sel = self.currentSel {
|
|
|
- self.handdler.showSelection(sel)
|
|
|
- } else {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.messageText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self.window)!)
|
|
|
- }
|
|
|
- } else {
|
|
|
- if self.finding_ {
|
|
|
- return
|
|
|
- }
|
|
|
- self.finding_ = true
|
|
|
- let searchS = self.searchInputView.stringValue
|
|
|
- let opt = self.fetchSearchOptions()
|
|
|
- self._beginLoading()
|
|
|
- DispatchQueue.global().async {
|
|
|
- let datas = self.handdler.pdfView?.document.startFindEditText(from: nil, with: searchS, options: opt)
|
|
|
- DispatchQueue.main.async {
|
|
|
- self._endLoading()
|
|
|
- self.finding_ = false
|
|
|
- let sel = datas?.first?.first
|
|
|
- if sel == nil {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.messageText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self.window)!)
|
|
|
- return
|
|
|
- }
|
|
|
- self.currentSel = sel
|
|
|
- self.handdler.showSelection(sel)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @objc private func _nextAction(_ sender: NSButton) {
|
|
|
- let isEditing = self.handdler.pdfView?.isEditing() ?? false
|
|
|
- if isEditing == false {
|
|
|
- guard let model = self.handdler.searchResults.safe_element(for: self.handdler.showIdx+1) as? KMSearchMode else {
|
|
|
- return
|
|
|
- }
|
|
|
- self.handdler.showIdx += 1
|
|
|
- self.handdler.showSelection(model.selection)
|
|
|
- } else {
|
|
|
- if let _ = self.currentSel {
|
|
|
- self.currentSel = self.handdler.pdfView?.document.findBackwordEditText()
|
|
|
- if let sel = self.currentSel {
|
|
|
- self.handdler.showSelection(sel)
|
|
|
- } else {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.messageText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self.window)!)
|
|
|
- }
|
|
|
- } else {
|
|
|
- if self.finding_ {
|
|
|
- return
|
|
|
- }
|
|
|
- self.finding_ = true
|
|
|
- let searchS = self.searchInputView.stringValue
|
|
|
- let opt = self.fetchSearchOptions()
|
|
|
- self._beginLoading()
|
|
|
- DispatchQueue.global().async {
|
|
|
-
|
|
|
- let datas = self.handdler.pdfView?.document.startFindEditText(from: nil, with: searchS, options: opt)
|
|
|
- DispatchQueue.main.async {
|
|
|
- self._endLoading()
|
|
|
- self.finding_ = false
|
|
|
- let sel = datas?.first?.first
|
|
|
- if sel == nil {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.messageText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self.window)!)
|
|
|
- return
|
|
|
- }
|
|
|
- self.currentSel = sel
|
|
|
- self.handdler.showSelection(sel)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @objc private func _checkAction(_ sender: NSButton) {
|
|
|
- self.currentSel = nil
|
|
|
- }
|
|
|
-
|
|
|
- @objc private func _searchTabAction(_ sender: NSButton) {
|
|
|
- self.switchType(.search, animate: true)
|
|
|
- }
|
|
|
-
|
|
|
- @objc private func _replaceTabAction(_ sender: NSButton) {
|
|
|
- self.switchType(.replace, animate: true)
|
|
|
- }
|
|
|
-
|
|
|
- @objc private func _replaceAction(_ sender: NSButton) {
|
|
|
- let isEditing = self.handdler.pdfView?.isEditing() ?? false
|
|
|
- if isEditing == false {
|
|
|
- NSSound.beep()
|
|
|
- return
|
|
|
- }
|
|
|
- if let sel = self.currentSel {
|
|
|
- let searchS = self.searchInputView.stringValue
|
|
|
- let replaceS = self.replaceInputView.stringValue
|
|
|
- let success = self.handdler.replace(searchS: searchS, replaceS: replaceS, sel: sel) { [weak self] newSel in
|
|
|
- self?.handdler.showSelection(newSel)
|
|
|
- }
|
|
|
- if success {
|
|
|
-// self.handdler.showSelection(sel)
|
|
|
- }
|
|
|
- } else { // 先查找
|
|
|
- if self.finding_ {
|
|
|
- return
|
|
|
- }
|
|
|
- self.finding_ = true
|
|
|
- let searchS = self.searchInputView.stringValue
|
|
|
- let opt = self.fetchSearchOptions()
|
|
|
- self._beginLoading()
|
|
|
- DispatchQueue.global().async {
|
|
|
- let datas = self.handdler.pdfView?.document.startFindEditText(from: nil, with: searchS, options: opt)
|
|
|
- DispatchQueue.main.async {
|
|
|
- self._endLoading()
|
|
|
- self.finding_ = false
|
|
|
- let sel = datas?.first?.first
|
|
|
- if sel == nil {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.messageText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self.window)!)
|
|
|
- return
|
|
|
- }
|
|
|
- self.currentSel = sel
|
|
|
- self.handdler.showSelection(sel)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @objc private func _replaceAllAction(_ sender: NSButton) {
|
|
|
- let isEditing = self.handdler.pdfView?.isEditing() ?? false
|
|
|
- if isEditing == false {
|
|
|
- NSSound.beep()
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- let datas = self.handdler.pdfView?.document.findEditSelections() ?? []
|
|
|
- if datas.isEmpty {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.informativeText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.beginSheetModal(for: NSApp.mainWindow!)
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self.window)!)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- if self.finding_ {
|
|
|
- return
|
|
|
- }
|
|
|
- self.finding_ = true
|
|
|
- let searchS = self.searchInputView.stringValue
|
|
|
- let replaceS = self.replaceInputView.stringValue
|
|
|
- self._beginLoading()
|
|
|
- DispatchQueue.global().async {
|
|
|
- self.handdler.pdfView?.document.replaceAllEditText(with: searchS, toReplace: replaceS)
|
|
|
- self.currentSel = nil
|
|
|
-
|
|
|
- DispatchQueue.main.async {
|
|
|
- self._endLoading()
|
|
|
- self.finding_ = false
|
|
|
- self.handdler.pdfView?.setHighlightedSelection(nil, animated: false)
|
|
|
- self.handdler.pdfView?.setNeedsDisplayForVisiblePages()
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private func fetchSearchOptions() -> CPDFSearchOptions {
|
|
|
- var opt = CPDFSearchOptions()
|
|
|
- let isCase = self.caseSensitiveCheck.state == .off
|
|
|
- if isCase {
|
|
|
- opt.insert(.caseSensitive)
|
|
|
- }
|
|
|
- let isWholeWord = self.matchWholeCheck.state == .on
|
|
|
- if isWholeWord {
|
|
|
- opt.insert(.matchWholeWord)
|
|
|
- }
|
|
|
- return opt
|
|
|
- }
|
|
|
-
|
|
|
- private func updateViewColor() {
|
|
|
- let isDark = KMAppearance.isDarkMode()
|
|
|
- if isDark {
|
|
|
-// self.window?.backgroundColor = NSColor(hex: "#393C3E")
|
|
|
- self.window?.contentView?.wantsLayer = true
|
|
|
- self.window?.contentView?.layer?.backgroundColor = NSColor(hex: "#393C3E").cgColor
|
|
|
-
|
|
|
- self.searchInputBox.borderColor = NSColor(hex: "#56585A")
|
|
|
- self.replaceInputBox.borderColor = NSColor(hex: "#56585A")
|
|
|
- } else {
|
|
|
-// self.window?.backgroundColor = .white
|
|
|
- self.window?.contentView?.wantsLayer = true
|
|
|
- self.window?.contentView?.layer?.backgroundColor = .white
|
|
|
-
|
|
|
- self.searchInputBox.borderColor = NSColor(hex: "#DADBDE")
|
|
|
- self.replaceInputBox.borderColor = NSColor(hex: "#DADBDE")
|
|
|
- }
|
|
|
-
|
|
|
- self.switchType(self.type_)
|
|
|
- }
|
|
|
-
|
|
|
- func switchType(_ type: KMSearchReplaceType, animate: Bool = false) {
|
|
|
- if type == .replace {
|
|
|
- if IAPProductsManager.default().isAvailableAllFunction() == false {
|
|
|
-// KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
|
|
|
- let winC = KMPurchaseCompareWindowController.sharedInstance()
|
|
|
- winC?.showWindow(nil)
|
|
|
- guard let win = winC?.window else {
|
|
|
- return
|
|
|
- }
|
|
|
- self.window?.addChildWindow(win, ordered: .above)
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- self.type_ = type
|
|
|
- let isDark = KMAppearance.isDarkMode()
|
|
|
- var selectedColor = NSColor(hex: "0E1114")
|
|
|
- var unSelectedColor = NSColor(hex: "757780")
|
|
|
- if isDark {
|
|
|
- selectedColor = .white
|
|
|
- unSelectedColor = NSColor(hex: "#7E7F85")
|
|
|
- }
|
|
|
-
|
|
|
- if type == .search { // 248 112
|
|
|
- self.tabSelectedLineLeftConst.animator().constant = 24
|
|
|
-
|
|
|
- self.searchTabButton.setTitleColor(selectedColor)
|
|
|
- self.searchTabButton.image = NSImage(named: "KMImageNameSearchIcon")
|
|
|
- self.replaceTabButton.setTitleColor(unSelectedColor)
|
|
|
- self.replaceTabButton.image = NSImage(named: "KMImageNameReplaceUnselectedIcon")
|
|
|
-
|
|
|
-// DispatchQueue.main.async {
|
|
|
- self.replaceBox.isHidden = true
|
|
|
- self.bottomBarBox.isHidden = true
|
|
|
-// }
|
|
|
-
|
|
|
- var frame = self.window?.frame ?? .zero
|
|
|
-// let height: CGFloat = 248+20
|
|
|
- let height: CGFloat = 112
|
|
|
- let heightOffset = frame.size.height - height
|
|
|
- frame.origin.y += heightOffset
|
|
|
- frame.size.height = height
|
|
|
- self.window?.setFrame(frame, display: true, animate: animate)
|
|
|
- self.window?.minSize = frame.size
|
|
|
- self.window?.maxSize = frame.size
|
|
|
- } else if type == .replace { // 388 208
|
|
|
- self.tabSelectedLineLeftConst.animator().constant = 140
|
|
|
-
|
|
|
- self.searchTabButton.setTitleColor(unSelectedColor)
|
|
|
- self.searchTabButton.image = NSImage(named: "KMImageNameSearchUnselectedIcon")
|
|
|
- self.replaceTabButton.setTitleColor(selectedColor)
|
|
|
- self.replaceTabButton.image = NSImage(named: "KMImageNameReplaceIcon")
|
|
|
-
|
|
|
- DispatchQueue.main.async {
|
|
|
- self.replaceBox.isHidden = false
|
|
|
- self.bottomBarBox.isHidden = false
|
|
|
- }
|
|
|
-
|
|
|
- var frame = self.window?.frame ?? .zero
|
|
|
- let height:CGFloat = 208
|
|
|
- let heightOffset = frame.size.height-height
|
|
|
- frame.origin.y += heightOffset
|
|
|
- frame.size.height = height
|
|
|
- self.window?.setFrame(frame, display: true, animate: animate)
|
|
|
- self.window?.minSize = frame.size
|
|
|
- self.window?.maxSize = frame.size
|
|
|
-
|
|
|
- // 将事件回调出去
|
|
|
- self.replaceCallback?()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private func _beginLoading() {
|
|
|
- self.window?.contentView?.beginLoading()
|
|
|
- }
|
|
|
-
|
|
|
- private func _endLoading() {
|
|
|
- self.window?.contentView?.endLoading()
|
|
|
- }
|
|
|
-
|
|
|
- func startModal(_ sender: AnyObject?) {
|
|
|
- NSApp.stopModal()
|
|
|
-
|
|
|
- var modalCode: NSApplication.ModalResponse?
|
|
|
- if let _win = self.window {
|
|
|
- self._modalSession = NSApp.beginModalSession(for: _win)
|
|
|
- repeat {
|
|
|
- modalCode = NSApp.runModalSession(self._modalSession!)
|
|
|
- } while (modalCode == .continue)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func endModal(_ sender: AnyObject?) {
|
|
|
- if let session = self._modalSession {
|
|
|
- NSApp.stopModal()
|
|
|
- NSApp.endModalSession(session)
|
|
|
- self.window?.orderOut(self)
|
|
|
- }
|
|
|
- if let winC = self.window?.kmCurrentWindowC, winC.isEqual(to: self) {
|
|
|
- self.window?.kmCurrentWindowC = nil
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // MARK: - Noti Methods
|
|
|
-
|
|
|
- @objc func themeChanged(_ notification: Notification) {
|
|
|
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
|
|
- self.updateViewColor()
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension KMSearchReplaceWindowController: NSTextFieldDelegate {
|
|
|
- func controlTextDidEndEditing(_ obj: Notification) {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- func controlTextDidChange(_ obj: Notification) {
|
|
|
- if self.searchInputView.isEqual(to: obj.object) { // 搜索输入框
|
|
|
- if self.searchInputView.stringValue.isEmpty {
|
|
|
- self.previousButton.isEnabled = false
|
|
|
- self.nextButton.isEnabled = false
|
|
|
- self.replaceButton.isEnabled = false
|
|
|
- self.replaceAllButton.isEnabled = false
|
|
|
- } else {
|
|
|
- self.previousButton.isEnabled = true
|
|
|
- self.nextButton.isEnabled = true
|
|
|
- self.replaceButton.isEnabled = true
|
|
|
- self.replaceAllButton.isEnabled = true
|
|
|
-
|
|
|
- self.currentSel = nil
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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 == self.searchInputView {
|
|
|
- let isCase = self.caseSensitiveCheck.state == .off
|
|
|
- let isWholeWord = self.matchWholeCheck.state == .on
|
|
|
- let isEditing = self.handdler.pdfView?.isEditing() ?? false
|
|
|
- if isEditing == false {
|
|
|
- if self.finding_ {
|
|
|
- return false
|
|
|
- }
|
|
|
- self.finding_ = true
|
|
|
- self._beginLoading()
|
|
|
- self.handdler.search(keyword: self.searchInputView.stringValue, isCase: isCase, isWholeWord: isWholeWord, callback: { [weak self] datas in
|
|
|
- self?.finding_ = false
|
|
|
- self?._endLoading()
|
|
|
-
|
|
|
- guard let sels = datas, sels.isEmpty == false else {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.informativeText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self?.window)!)
|
|
|
- return
|
|
|
- }
|
|
|
- if let sel = datas?.first?.selection {
|
|
|
- self?.handdler.showIdx = 0
|
|
|
- self?.handdler.showSelection(sel)
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- if self.finding_ {
|
|
|
- return false
|
|
|
- }
|
|
|
- self.finding_ = true
|
|
|
- let searchS = self.searchInputView.stringValue
|
|
|
- let opt = self.fetchSearchOptions()
|
|
|
- self._beginLoading()
|
|
|
- DispatchQueue.global().async {
|
|
|
- let datas = self.handdler.pdfView?.document.findEditAllPageString(searchS, with: opt) ?? []
|
|
|
- DispatchQueue.main.async {
|
|
|
- self.finding_ = false
|
|
|
- self._endLoading()
|
|
|
- if datas.isEmpty {
|
|
|
- let alert = NSAlert()
|
|
|
- alert.informativeText = NSLocalizedString("No related content found, please change keyword.", comment: "")
|
|
|
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
|
|
|
-// alert.beginSheetModal(for: NSApp.mainWindow!)
|
|
|
-// alert.runModal()
|
|
|
- alert.beginSheetModal(for: (self.window)!)
|
|
|
- return
|
|
|
- }
|
|
|
- self.currentSel = datas.first?.first
|
|
|
- if let sel = self.currentSel {
|
|
|
- self.handdler.showSelection(sel)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return true
|
|
|
- default:
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
-}
|