Browse Source

【2025】【BOTA】搜索列表功能串接

tangchao 3 months ago
parent
commit
b6334812a4

+ 42 - 67
PDF Office/PDF Master/KMClass/KMPDFViewController/KMMainViewController.swift

@@ -1657,42 +1657,12 @@ struct KMNMWCFlags {
     
     // 搜索 & 替换
     
-    func showSearchPopWindow(type: KMNBotaSearchType, handdler: KMNSearchHanddler) {
-        if type == .search {
-            self.view.window?.makeFirstResponder(nil)
-            let winC = KMSearchReplaceWindowController(with: listView, type: .search)
-            self.currentWindowController = winC
-            winC.replaceCallback = { [weak self] in
-                let toolMode = self?.listView.toolMode ?? .none
-                let isEditing = self?.listView.isEditing() ?? false
-                if toolMode == .editPDFToolMode &&  isEditing {
-                    
-                } else { // 进入内容编辑模式
-                    self?.viewManager.toolMode = .Edit
-                    self?.updatePDFViewAnnotationMode()
-                }
-            }
-            winC.itemClick = { idx, _ in
-                if idx == 1 {
-                    self.toggleOpenLeftSide(pdfSideBarType: .search)
-                    
-                    
-                }
-            }
-            let targetView = self.pdfToolbarController?.leftViewButton
-            let point = targetView?.convert(targetView?.frame.origin ?? .zero, to: nil) ?? .zero
-            // 200 248
-            let x = point.x + (self.view.window?.frame.origin.x ?? 0) - 32
-            let y = point.y + (self.view.window?.frame.origin.y ?? 0) - 112 - 32
-            
-            let winFramePoint = NSPoint(x: x, y: y)
-            winC.window?.setFrameOrigin(winFramePoint)
-            
-            winC.update(keyborad: handdler.searchKey, replaceKey: handdler.replaceKey, results: handdler.searchResults)
-            
-//            winC.startModal(nil)
-            self.view.window?.addChildWindow(winC.window!, ordered: .above)
-        } else if type == .replace {
+    func showSearchPopWindow(type: KMNBotaSearchType, keyborad: String?, replaceText: String?, results: [KMSearchMode]) {
+        let toolMode = self.listView.toolMode ?? .none
+        let isEditing = self.listView.isEditing() ?? false
+        
+        var winH: CGFloat = 112
+        if type == .replace {
             if IAPProductsManager.default().isAvailableAllFunction() == false {
                 let winC = KMPurchaseCompareWindowController.sharedInstance()
                 winC?.kEventName = "Reading_ReplaceText_BuyNow"
@@ -1700,46 +1670,51 @@ struct KMNMWCFlags {
                 return
             }
             
-            self.view.window?.makeFirstResponder(nil)
-            let toolMode = self.listView.toolMode ?? .none
-            let isEditing = self.listView.isEditing() ?? false
             if toolMode == .editPDFToolMode && isEditing {
                 
             } else { // 进入内容编辑模式
                 viewManager.toolMode = .Edit
                 updatePDFViewAnnotationMode()
             }
-            
-            let winC = KMSearchReplaceWindowController(with: self.listView, type: .replace)
-            self.currentWindowController = winC
-            winC.replaceCallback = { [weak self] in
-                let toolMode = self?.listView.toolMode ?? .none
-                let isEditing = self?.listView.isEditing() ?? false
-                if toolMode == .editPDFToolMode && isEditing {
-                    
-                } else { // 进入内容编辑模式
-                    self?.viewManager.toolMode = .Edit
-                    self?.updatePDFViewAnnotationMode()
-                 }
+            winH = 208
+        }
+        
+        self.view.window?.makeFirstResponder(nil)
+        let winC = KMSearchReplaceWindowController(with: listView, type: type)
+        self.currentWindowController = winC
+        
+        winC.replaceCallback = { [weak self] in
+            let toolMode = self?.listView.toolMode ?? .none
+            let isEditing = self?.listView.isEditing() ?? false
+            if toolMode == .editPDFToolMode &&  isEditing {
+                
+            } else { // 进入内容编辑模式
+                self?.viewManager.toolMode = .Edit
+                self?.updatePDFViewAnnotationMode()
             }
-            
-            winC.itemClick = { idx, _ in
-                if idx == 1 {
-                    self.toggleOpenLeftSide(pdfSideBarType: .search)
+        }
+        winC.itemClick = { [weak self] idx, params in
+            if idx == 1 {
+                self?.toggleOpenLeftSide(pdfSideBarType: .search)
+                
+                guard let handdler = params.first as? KMNSearchHanddler else {
+                    return
                 }
+                let viewC = self?.leftSideViewController.searchViewController
+                viewC?.update(keyborad: handdler.searchKey, replaceKey: handdler.replaceKey, results: handdler.searchResults)
             }
-            
-            let targetView = self.pdfToolbarController?.leftViewButton
-            let point = targetView?.convert(targetView?.frame.origin ?? .zero, to: nil) ?? .zero
-            // 200 248
-            let x = point.x + (self.view.window?.frame.origin.x ?? 0) - 32
-            let y = point.y + (self.view.window?.frame.origin.y ?? 0) - 208 - 32
-            let winFramePoint = NSPoint(x: x, y: y)
-            winC.window?.setFrameOrigin(winFramePoint)
-            
-//            winC.startModal(nil)
-            self.view.window?.addChildWindow(winC.window!, ordered: .above)
         }
+        let targetView = self.pdfToolbarController?.leftViewButton
+        let point = targetView?.convert(targetView?.frame.origin ?? .zero, to: nil) ?? .zero
+        // 200 248
+        let x = point.x + (self.view.window?.frame.origin.x ?? 0) - 32
+        let y = point.y + (self.view.window?.frame.origin.y ?? 0) - winH - 32
+        
+        let winFramePoint = NSPoint(x: x, y: y)
+        winC.window?.setFrameOrigin(winFramePoint)
+        
+        winC.update(keyborad: keyborad, replaceKey: replaceText, results: results)
+        self.view.window?.addChildWindow(winC.window!, ordered: .above)
     }
     
 }
@@ -3767,7 +3742,7 @@ extension KMMainViewController: KMNLeftSideViewControllerDelegate {
         closeLeftPane()
         
         let handdler = controller.searchViewC.handdler
-        showSearchPopWindow(type: handdler.type, handdler: handdler)
+        showSearchPopWindow(type: handdler.type, keyborad: handdler.searchKey, replaceText: handdler.replaceKey, results: handdler.searchResults)
     }
 }
 

+ 137 - 196
PDF Office/PDF Master/KMClass/Left/Search/Controller/KMBotaSearchViewController.swift

@@ -17,6 +17,7 @@ extension KMNSearchKey.caseSensitive {
 }
 
 enum KMNBotaSearchType: Int {
+    case none = 0
     case search = 1
     case replace = 2
 }
@@ -28,9 +29,7 @@ enum KMNBotaSearchType: Int {
 class KMBotaSearchViewController: KMNBotaBaseViewController {
     @IBOutlet weak var searchField: NSSearchField!
     @IBOutlet weak var segmentedControl: KMSegmentedControl!
-    
     @IBOutlet weak var topView: NSBox!
-    
     @IBOutlet weak var topHeightConst: NSLayoutConstraint!
     
     var contentView: NSView? {
@@ -62,7 +61,6 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
     
     private var emptyView_: ComponentEmpty = {
         let view = ComponentEmpty()
-        // , image: NSImage(named: "KMImageNameOutlineEmpty")
         view.properties = ComponentEmptyProperty(emptyType: .noSearch, state: .normal, text: KMLocalizedString("No Results"), subText: KMLocalizedString(""))
         return view
     }()
@@ -81,12 +79,7 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
     }
     
     private var datas: [Any] = []
-    
-    deinit {
-        KMPrint("KMBotaSearchViewController deinit.")
-        
-        NotificationCenter.default.removeObserver(self)
-    }
+    private var searchResultIndex_: Int = -1
     
     override func loadView() {
         super.loadView()
@@ -121,10 +114,7 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
             guard let string = info?[.newKey] as? String else {
                 return
             }
-            
-            let isCase = KMDataManager.ud_bool(forKey: KMNSearchKey.caseSensitive.botaSearch)
-            let isWholeWord = KMDataManager.ud_bool(forKey: KMNSearchKey.wholeWords.botaSearch)
-            handdler.search(keyword: string, isCase: isCase, isWholeWord: isWholeWord) { [unowned self] results in
+            self.search(keyword: string) { [unowned self] results in
                 searchResults = results ?? []
                 
                 showResult()
@@ -141,44 +131,8 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
         self.emptySearchLabel.stringValue = KMLocalizedString("")
         self.emptySearchLabel.textColor = KMAppearance.Layout.h1Color()
         self.emptyBox.fillColor = KMAppearance.Layout.l0Color()
-//        self.searchLabel.stringValue = KMLocalizedString("Search")
-//        self.searchLabel.textColor = KMAppearance.Layout.h0Color()
-//        self.searchTips.stringValue = KMLocalizedString("Search")
-//        self.searchTips.textColor = KMAppearance.Layout.h2Color()
-//        self.searchResultsLabel.textColor = KMAppearance.Layout.h1Color()
-//        self.pageLabel.stringValue = KMLocalizedString("Page")
-//        self.pageLabel.textColor = KMAppearance.Layout.h1Color()
-//        self.searchResultsView.isHidden = true
-        
-//        self.searchDomeButton.title = KMLocalizedString("Done")
-//        self.searchDomeButton.toolTip = KMLocalizedString("Done")
-//        self.searchDomeButton.setTitleColor(KMAppearance.Layout.w0Color())
-//        self.searchDomeButton.wantsLayer = true
-//        self.searchDomeButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
-//        self.searchDomeButton.layer?.cornerRadius = 4.0
-    //    self.searchDomeButton.hidden = YES;
-        
-//        self.searchField.wantsLayer = true
-    //    self.searchField.layer.backgroundColor = [KMAppearance KMColor_Layout_L1].CGColor;
-//        self.searchField.layer?.cornerRadius = 1.0
-//        self.searchField.layer?.borderWidth = 1.0
-//        self.searchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor
-        
-//        self.searchBox.fillColor = KMAppearance.Interactive.s0Color()
-    //    self.searchField.hidden = YES;
-//        self.searchBox.downCallback = { [unowned self] downEntered, box, _ in
-//            if (downEntered) {
-//                self.searchField.isHidden = false
-//                self.searchDomeButton.isHidden = false
-//                self.searchBox.isHidden = true
-//                self.searchField.becomeFirstResponder()
-//            }
-//        }
-        
-//        self.searchBox.isHidden = true
         
         contentView = tableView.enclosingScrollView
-        
         tableView.menuClickedAction = { [unowned self] point in
             let idxs = self.tableView.selectedRowIndexes.count
             
@@ -188,6 +142,12 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
                 return NSMenu()
             }
             
+            let hideNotes = handdler.hideNotes()
+            let allowsNotes = handdler.allowsNotes()
+            if hideNotes || allowsNotes == false {
+                return NSMenu()
+            }
+            
             guard let model =  self.datas[row] as? KMSearchMode else {
                 return NSMenu()
             }
@@ -218,35 +178,6 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
             self.menuGroupView_?.showWithPoint(CGPoint(x: point.x, y: point.y - viewHeight), relativeTo: self.tableView)
             return NSMenu()
         }
-        
-//        var rowIndexes = self.findTableView.selectedRowIndexes
-//        let row = self.findTableView.clickedRow
-//        if (row != -1) {
-//            if rowIndexes.contains(row) == false {
-//                rowIndexes = IndexSet(integer: row)
-//            }
-//
-//            var selections: [CPDFSelection] = []
-//            for (i, data) in self.searchResults.enumerated() {
-//                if rowIndexes.contains(i) {
-//                    selections.append(data.selection)
-//                }
-//            }
-//            let hideNotes = self.hideNotes()
-//            let allowsNotes = self.allowsNotes()
-//            if hideNotes  == false && allowsNotes {
-//                item = menu.addItem(withTitle: KMLocalizedString("Add New Circle"), action: #selector(addAnnotationsForSelections), target: self, tag: CAnnotationType.circle.rawValue)
-//                item?.representedObject = selections
-//                item = menu.addItem(withTitle: KMLocalizedString("Add New Rectangle"), action: #selector(addAnnotationsForSelections), target: self, tag: CAnnotationType.square.rawValue)
-//                item?.representedObject = selections
-//                item = menu.addItem(withTitle: KMLocalizedString("Add New Highlight"), action: #selector(addAnnotationsForSelections), target: self, tag: CAnnotationType.highlight.rawValue)
-//                item?.representedObject = selections
-//                item = menu.addItem(withTitle: KMLocalizedString("Add New Underline"), action: #selector(addAnnotationsForSelections), target: self, tag: CAnnotationType.underline.rawValue)
-//                item?.representedObject = selections
-//                item = menu.addItem(withTitle: KMLocalizedString("Add New Strikethrough"), action: #selector(addAnnotationsForSelections), target: self, tag: CAnnotationType.strikeOut.rawValue)
-//                item?.representedObject = selections
-//            }
-//        }
     }
     
     override func viewDidLoad() {
@@ -255,21 +186,12 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
         self.tableView.delegate = self
         self.tableView.dataSource = self
         self.tableView.botaDelegate = self
-//        self.tableView.menu?.delegate = self
-        
-//        self.mwcFlags.wholeWordSearch = KMDataManager.ud_integer(forKey: SKWholeWordSearchKey)
-//        self.mwcFlags.caseInsensitiveSearch = KMDataManager.ud_integer(forKey: SKCaseInsensitiveSearchKey)
-        
-//        self.tableView.backgroundColor = KMAppearance.Layout.l0Color()
-        self.tableView.tableColumn(withIdentifier: kPageColumnId)?.headerCell.title = KMLocalizedString("Page")
     }
     
     override func viewDidAppear() {
         super.viewDidAppear()
         
 //        self.searchField.becomeFirstResponder()
-        self.updateViewColor()
-        DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChanged), name: NSApplication.interfaceThemeChangedNotification, object: nil)
     }
     
     override func updateUILanguage() {
@@ -298,14 +220,6 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
         }
     }
     
-    func updateViewColor() {
-        if (KMAppearance.isDarkMode()) {
-//            self.searchField.layer?.backgroundColor = NSColor(red: 57.0/255.0, green: 60.0/255.0, blue: 62.0/255.0, alpha: 1).cgColor
-        } else {
-//            self.searchField.layer?.backgroundColor = .white
-        }
-    }
-    
     func showSearchView() {
         topContentView_?.showSearch()
         
@@ -325,6 +239,27 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
         topHeightConst.constant = topContentView_?.fetchContentHeight(type: handdler.type, hasResult: searchResults.isEmpty == false) ?? 0
     }
     
+    func update(keyborad: String?, replaceKey: String?, results: [KMSearchMode]) {
+//        searchItemView_.inputValue = keyborad
+//        replaceItemView_.inputValue = replaceKey
+//        
+//        if results.isEmpty == false {
+//            handdler.searchResults = results
+//            self.currentSel = results.first?.selection
+//            if let sel = self.currentSel {
+//                self.handdler.showSelection(sel)
+//            }
+//        }
+//        
+//        updateButtonStatus()
+    }
+    
+    func search(keyword: String, callback: @escaping (([KMBotaSearchSectionModel]?) -> Void)) {
+        let isCase = KMDataManager.ud_bool(forKey: KMNSearchKey.caseSensitive.botaSearch)
+        let isWholeWord = KMDataManager.ud_bool(forKey: KMNSearchKey.wholeWords.botaSearch)
+        handdler.search(keyword: keyword, isCase: isCase, isWholeWord: isWholeWord, callback: callback)
+    }
+    
     // MARK: - Group View
     
     func showSearchGroupView(sender: ComponentButton) {
@@ -372,43 +307,12 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
         searchGroupTarget = sender
     }
     
-    @objc func themeChanged(_ notification: NSNotification) {
-        DispatchQueue.main.asyncAfter(deadline: .now()+0.3) {
-            self.updateViewColor()
-        }
-    }
-    
     @IBAction func searchDomeButtonAtion(_ sender: AnyObject) {
         self.searchField.isHidden = true
         self.searchDomeButton.isHidden = true
         self.searchBox.isHidden = false
     }
     
-    @objc func toggleWholeWordSearch(_ sender: AnyObject?) {
-//        if self.mwcFlags.wholeWordSearch == 1 {
-//            self.mwcFlags.wholeWordSearch = 0
-//        } else {
-//            self.mwcFlags.wholeWordSearch = 1
-//        }
-//        if self.searchField.stringValue.isEmpty == false {
-//            self.search(self.searchField)
-//        }
-//        KMDataManager.ud_set(self.mwcFlags.wholeWordSearch, forKey: SKWholeWordSearchKey)
-    }
-    
-    @objc func toggleCaseInsensitiveSearch(_ sender: AnyObject?) {
-//        if self.mwcFlags.caseInsensitiveSearch == 0 {
-//            self.mwcFlags.caseInsensitiveSearch = 1
-//        } else {
-//            self.mwcFlags.caseInsensitiveSearch = 0
-//        }
-//
-//        if self.searchField.stringValue.isEmpty == false {
-//            self.search(self.searchField)
-//        }
-//        KMDataManager.ud_set(self.mwcFlags.caseInsensitiveSearch, forKey: SKCaseInsensitiveSearchKey)
-    }
-    
     @objc func goToSelectedFindResults(_ sender: AnyObject?) {
 //        guard let olView = sender as? NSTableView, olView.clickedRow != -1 else {
 //            NSSound.beep()
@@ -417,18 +321,6 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
 //        self.updateFindResultHighlightsForDirection(.directSelection)
     }
     
-    @objc func searchAction(_ sender: NSSearchField) {
-//        if sender.stringValue.isEmpty {
-//            self.applySearchTableHeader("")
-//        }
-//        self.delegate?.searchAction?(searchString: sender.stringValue, isCase: self.mwcFlags.caseInsensitiveSearch == 1)
-        
-        handdler.search(keyword: sender.stringValue, isCase: false, isWholeWord: false) { [weak self] results in
-            self?.searchResults = results ?? []
-            self?.tableView.reloadData()
-        }
-    }
-    
     @objc func addAnnotationsForSelections(_ sender: NSMenuItem) {
         for selection in menuSections_ {
 //            self.listView?.addAnnotation(with: CAnnotationType(rawValue: sender.tag) ?? .circle, selection: selection, page: selection.page, bounds: selection.bounds)
@@ -445,6 +337,55 @@ class KMBotaSearchViewController: KMNBotaBaseViewController {
 //            self.searchResultsView.isHidden = true
         }
     }
+    
+    func updateFindResultHighlightsForDirection(_ direction: NSWindow.SelectionDirection) {
+        var findResults: [KMSearchMode] = handdler.searchResults
+        if (findResults.count == 0) {
+            handdler.showSelection(nil)
+        } else {
+            if direction == .directSelection {
+                self.searchResultIndex_ = 0
+            } else if (direction == .selectingNext) {
+                self.searchResultIndex_ += 1
+                if self.searchResultIndex_ >= findResults.count {
+                    self.searchResultIndex_ = 0
+                }
+            } else if (direction == .selectingPrevious) {
+                self.searchResultIndex_ -= 1
+                if self.searchResultIndex_ < 0 {
+                    self.searchResultIndex_ = findResults.count-1
+                }
+            }
+
+            let currentSel = findResults[self.searchResultIndex_].selection
+            if currentSel.hasCharacters() {
+                let page = currentSel.safeFirstPage()
+                var rect = NSZeroRect
+
+                for model in findResults {
+                    if let data = page, model.selection.pages().contains(data) {
+                        rect = NSUnionRect(rect, model.selection.bounds(for: data))
+                    }
+                }
+                let FIND_RESULT_MARGIN = 50.0
+                rect = NSIntersectionRect(NSInsetRect(rect, -FIND_RESULT_MARGIN, -FIND_RESULT_MARGIN), page?.bounds(for: .cropBox) ?? .zero)
+                handdler.pdfView?.go(to: page)
+                handdler.pdfView?.go(to: rect, on: page)
+            }
+            
+            if currentSel.hasCharacters() {
+                let bColor = NSColor(red: 236/255.0, green: 241/255.0, blue: 83/255.0, alpha: 0.5)
+                let color = NSColor(red: 219/255.0, green: 220/255.0, blue: 3/255.0, alpha: 0.5)
+                handdler.pdfView?.setHighlight(currentSel, forBorderColor: .clear, fill: color, animated: true)
+                handdler.pdfView?.go(to: currentSel, animated: true)
+                handdler.pdfView?.setCurrentSelection(currentSel, animate: true)
+            }
+//            let mode =  self.listView?.toolMode ?? .none
+//            if mode == .moveToolMode || mode == .magnifyToolMode || mode == .selectToolMode {
+//                self.listView?.setCurrentSelection(nil, animate: false)
+//            }
+        }
+    }
 }
 
 // MARK: - NSTableViewDelegate, NSTableViewDataSource
@@ -531,29 +472,21 @@ extension KMBotaSearchViewController: NSTableViewDelegate, NSTableViewDataSource
     }
     
     func tableViewSelectionDidChange(_ notification: Notification) {
-//        if self.stopRepeatLoad == true {
-//
-//        } else {
-//            self.delegate?.controller?(controller: self, listViewSelectionDidChange: notification.object, info: nil)
-//        }
-        
-        
-            //            [self updateFindResultHighlightsForDirection:NSDirectSelection];
         let row = self.tableView.selectedRow
-        if row >= 0 {
-//            let model = handdler.searchResults[row]
-//            let isEditing =  self.listView?.isEditing() ?? false
-//            if isEditing {
-//                self.mainViewController?.srHanddler.showSelection(model.selection)
-//                return
-//            }
+        if row < 0 || row >= datas.count {
+            return
+        }
+        guard let model = datas[row] as? KMSearchMode else {
+            return
+        }
+        let isEditing =  handdler.pdfView?.isEditing() ?? false
+        if isEditing {
+            handdler.showSelection(model.selection)
+            return
+        }
             
-//            self.listView?.go(to: model.selection, animated: true)
-            //                self.listView?.setHighlightedSelection(model.selection, animated: true)
-            DispatchQueue.main.asyncAfter(deadline: .now()+0.3) {
-//                self.listView?.setHighlightedSelections([model.selection])
-//                self.listView?.setNeedsDisplayAnnotationViewForVisiblePages()
-            }
+        DispatchQueue.main.asyncAfter(deadline: .now()+0.3) {
+            self.handdler.showSelection(model.selection)
         }
     }
     
@@ -562,14 +495,22 @@ extension KMBotaSearchViewController: NSTableViewDelegate, NSTableViewDataSource
             KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
             return
         }
+        
         var string = ""
         for idx in rowIndexes {
-//            let match = handdler.searchResults[idx].selection
-//            string.append("* ")
-            //                [string appendFormat:NSLocalizedString(@"Page %@", @""), [match firstPageLabel]];
-//            string = string.appendingFormat(KMLocalizedString("Page %@"), "\(match.safeFirstPage()?.pageIndex() ?? 0)")
-            //                [string appendFormat:@"", [[match contextString] string]];
-//            string = string.appendingFormat(": %@\n", match.string() ?? "")
+            if idx < 0 || idx >= datas.count {
+                continue
+            }
+            guard let model = datas[idx] as? KMSearchMode else {
+                continue
+            }
+            
+            let match = model.selection
+            string.append("* ")
+//                [string appendFormat:NSLocalizedString(@"Page %@", @""), [match firstPageLabel]];
+            string = string.appendingFormat(KMLocalizedString("Page %@"), "\(match.safeFirstPage()?.pageIndex() ?? 0)")
+//                [string appendFormat:@"", [[match contextString] string]];
+            string = string.appendingFormat(": %@\n", match.string() ?? "")
         }
         let pboard = NSPasteboard.general
         pboard.clearContents()
@@ -586,7 +527,7 @@ extension KMBotaSearchViewController: KMBotaTableViewDelegate {
     }
     
     func tableViewMoveRight(_ aTableView: NSTableView) {
-//        self.updateFindResultHighlightsForDirection(.selectingNext)
+        updateFindResultHighlightsForDirection(.selectingNext)
     }
     
     func tableViewMoveUp(_ aTableView: NSTableView) {
@@ -600,16 +541,18 @@ extension KMBotaSearchViewController: KMBotaTableViewDelegate {
     }
     
     func tableView(_ aTableView: NSTableView, imageContextForRow rowIndex: Int) -> AnyObject? {
-        if rowIndex >= self.searchResults.count {
+        if rowIndex < 0 || rowIndex >= datas.count {
             return nil
         }
-//        let model = self.searchResults[rowIndex]
-//        let selection = model.selection
-//        let x = selection.bounds.origin.x + NSWidth(selection.bounds) * 0.5
-//        let y = selection.bounds.origin.y + NSHeight(selection.bounds) * 0.5
-//        let point = NSPoint(x: x, y: y)
-//        return CPDFDestination(document: self.pdfDocument(), pageIndex: Int(model.selectionPageIndex), at: point, zoom: self.scaleFactor().cgFloat)
-        return nil
+        guard let model = datas[rowIndex] as? KMSearchMode else {
+            return nil
+        }
+        
+        let selection = model.selection
+        let x = selection.bounds.origin.x + NSWidth(selection.bounds) * 0.5
+        let y = selection.bounds.origin.y + NSHeight(selection.bounds) * 0.5
+        let point = NSPoint(x: x, y: y)
+        return CPDFDestination(document: handdler.pdfDocument(), pageIndex: Int(model.selectionPageIndex), at: point, zoom: handdler.scaleFactor() ?? 0)
     }
     
 }
@@ -618,14 +561,10 @@ extension KMBotaSearchViewController: KMBotaTableViewDelegate {
 
 extension KMBotaSearchViewController: ComponentGroupDelegate {
     func componentGroupDidDismiss(group: ComponentGroup?) {
-//        if group == groupView_ {
-//            removeGroupView()
-//        } else if group == menuGroupView_ {
-//            group?.removeFromSuperview()
-//            menuGroupView_ = nil
-//        } else
-        if group == searchGroupView {
-//            searchGroupView_ = nil
+        if group == menuGroupView_ {
+            group?.removeFromSuperview()
+            menuGroupView_ = nil
+        } else if group == searchGroupView {
             searchGroupTarget?.properties.state = .normal
             searchGroupTarget?.reloadData()
             searchGroupTarget = nil
@@ -633,18 +572,6 @@ extension KMBotaSearchViewController: ComponentGroupDelegate {
     }
     
     func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) {
-//        if group == groupView_ {
-//            if let selItem = menuItemProperty {
-//                let index = group?.menuItemArr.firstIndex(of: selItem)
-//                if index == 0 {
-//                    expandAllComments(item: NSMenuItem())
-//                } else if index == 1 {
-//                    collapseAllComments(item: NSMenuItem())
-//                } else if index == 2 {
-//                    removeAllOutlineItem(item: NSMenuItem())
-//                }
-//            }
-//        } else
         if group == menuGroupView_ {
             if let selItem = menuItemProperty {
                 let index = group?.menuItemArr.firstIndex(of: selItem)
@@ -680,13 +607,27 @@ extension KMBotaSearchViewController: ComponentGroupDelegate {
                 let value = KMDataManager.ud_bool(forKey: key)
                 KMDataManager.ud_set(!value, forKey: key)
                 
-//                BOTAOutlineView.wholeWords = !value
+                if let data = topContentView_?.inputValue, data.isEmpty {
+                    search(keyword: data) { [weak self] results in
+                        self?.searchResults = results ?? []
+                        
+                        self?.showResult()
+                        self?.tableView.reloadData()
+                    }
+                }
             } else if idx == 4 {
                 let key = KMNSearchKey.caseSensitive.botaSearch
                 let value = KMDataManager.ud_bool(forKey: key)
                 KMDataManager.ud_set(!value, forKey: key)
                 
-//                BOTAOutlineView.caseSensitive = !value
+                if let data = topContentView_?.inputValue, data.isEmpty {
+                    search(keyword: data) { [weak self] results in
+                        self?.searchResults = results ?? []
+                        
+                        self?.showResult()
+                        self?.tableView.reloadData()
+                    }
+                }
             }
         }
     }

+ 20 - 2
PDF Office/PDF Master/KMClass/Left/Search/Tools/KMNSearchHanddler.swift

@@ -12,14 +12,32 @@ class KMNSearchHanddler: NSObject {
     
     var type: KMNBotaSearchType = .search
     
-    var searchKey: String = ""
-    var replaceKey: String = ""
+    var searchKey: String?
+    var replaceKey: String?
     
     var showIdx = 0
     
     var searchSectionResults: [KMBotaSearchSectionModel] = []
     var searchResults: [KMSearchMode] = []
     
+    func hideNotes() -> Bool {
+        let listView = pdfView as? CPDFListView
+        return  listView?.hideNotes ?? false
+    }
+    
+    func allowsNotes() -> Bool {
+        let listView = pdfView as? CPDFListView
+        return listView?.allowsNotes() ?? false
+    }
+    
+    func pdfDocument() -> CPDFDocument? {
+        return pdfView?.document
+    }
+    
+    func scaleFactor() -> CGFloat? {
+        return pdfView?.scaleFactor
+    }
+    
     func search(keyword: String, isCase: Bool, isWholeWord: Bool, callback: @escaping (([KMBotaSearchSectionModel]?) -> Void)) {
         guard let document = self.pdfView?.document else {
             NSSound.beep()

+ 18 - 1
PDF Office/PDF Master/KMClass/Left/Search/View/KMNBotaSearchTopView.swift

@@ -17,7 +17,6 @@ enum KMNBotaSearchTopItemKey: Int {
 }
 
 class KMNBotaSearchTopView: NSView, NibLoadable {
-    
     @IBOutlet weak var topBox: NSBox!
     @IBOutlet weak var centerBox: NSBox!
     @IBOutlet weak var bottomBox: NSBox!
@@ -91,6 +90,24 @@ class KMNBotaSearchTopView: NSView, NibLoadable {
         }
     }
     
+    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)
 

+ 31 - 61
PDF Office/PDF Master/KMClass/Left/Search/Window/KMSearchReplaceWindowController.swift

@@ -18,12 +18,6 @@ class KMSearchReplaceWindowController_Window: NSWindow {
     }
 }
 
-@objc enum KMSearchReplaceType: Int {
-    case none = 0
-    case search = 1
-    case replace = 2
-}
-
 class KMSearchReplaceWindowController: KMNBaseWindowController {
     @IBOutlet weak var titleBarBox: NSBox!
     @IBOutlet weak var tabBox: NSBox!
@@ -36,7 +30,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
     private var _modalSession: NSApplication.ModalSession?
     
     private var handdler = KMNSearchHanddler()
-    private var type_: KMSearchReplaceType = .search
+    private var type_: KMNBotaSearchType = .search
     
     private var currentSel: CPDFSelection?
     private var finding_ = false
@@ -75,7 +69,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
         }
     }
     
-    convenience init(with pdfView: CPDFView?, type: KMSearchReplaceType) {
+    convenience init(with pdfView: CPDFView?, type: KMNBotaSearchType) {
         self.init(windowNibName: "KMSearchReplaceWindowController")
         
         self.handdler.pdfView = pdfView
@@ -198,9 +192,9 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
         }
     }
     
-    func update(keyborad: String, replaceKey: String, results: [KMSearchMode]) {
-        searchItemView_.inputValue = keyborad
-        replaceItemView_.inputValue = replaceKey
+    func update(keyborad: String?, replaceKey: String?, results: [KMSearchMode]) {
+        searchItemView_.inputValue = keyborad ?? ""
+        replaceItemView_.inputValue = replaceKey ?? ""
         
         if results.isEmpty == false {
             handdler.searchResults = results
@@ -216,8 +210,6 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
     // MARK: - Actions
     
     @objc private func _closeAction(_ sender: NSButton) {
-//        self.endModal(sender)
-        
         self.window?.orderOut(nil)
         self.handdler.clearData()
     }
@@ -236,11 +228,8 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
                 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)!)
+                    _showNoResultsAlert()
+                    return
                 }
             } else {
                 if self.finding_ {
@@ -257,11 +246,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
                         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)!)
+                            self._showNoResultsAlert()
                             return
                         }
                         self.currentSel = sel
@@ -286,11 +271,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
                 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)!)
+                    _showNoResultsAlert()
                 }
             } else {
                 if self.finding_ {
@@ -308,11 +289,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
                         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)!)
+                            self._showNoResultsAlert()
                             return
                         }
                         self.currentSel = sel
@@ -365,11 +342,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
                     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)!)
+                        self._showNoResultsAlert()
                         return
                     }
                     self.currentSel = sel
@@ -388,12 +361,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
         
         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)!)
+            _showNoResultsAlert()
             return
         }
         
@@ -417,6 +385,21 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
         }
     }
     
+    private func _showNoResultsAlert() {
+        _ = _showAlert(style: .critical, message: KMLocalizedString("No related content found, please change keyword."), info: "", buttons: [KMLocalizedString("OK", comment: "")])
+    }
+    
+    private func _showAlert(style: NSAlert.Style, message: String, info: String, buttons: [String]) -> NSApplication.ModalResponse {
+        let alert = NSAlert()
+        alert.alertStyle = style
+        alert.messageText = message
+        alert.informativeText = info
+        for button in buttons {
+            alert.addButton(withTitle: button)
+        }
+        return alert.runModal()
+    }
+    
     private func fetchSearchOptions() -> CPDFSearchOptions {
         var opt = CPDFSearchOptions()
         let isCase = KMDataManager.ud_bool(forKey: KMNSearchKey.caseSensitive.botaSearch)
@@ -443,10 +426,9 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
         self.switchType(self.type_)
     }
     
-    func switchType(_ type: KMSearchReplaceType, animate: Bool = false) {
+    func switchType(_ type: KMNBotaSearchType, 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 {
@@ -467,12 +449,9 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
         }
         
         if type == .search { // 248 112
-//            DispatchQueue.main.async {
-                self.replaceBox.isHidden = true
-//            }
+            self.replaceBox.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
@@ -545,11 +524,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
                 self?._endLoading()
                 
                 guard let sels = self?.handdler.searchResults, 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)!)
+                    self?._showNoResultsAlert()
                     return
                 }
                 if let sel = sels.first?.selection {
@@ -571,12 +546,7 @@ class KMSearchReplaceWindowController: KMNBaseWindowController {
                     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)!)
+                        self._showNoResultsAlert()
                         return
                     }
                     self.currentSel = datas.first?.first