KMLeftSideViewController+Search.swift 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. //
  2. // KMLeftSideViewController+Search.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2023/12/24.
  6. //
  7. import Foundation
  8. private let _kRelevanceColumnId = NSUserInterfaceItemIdentifier(rawValue: "relevance")
  9. // MARK: - Methods
  10. extension KMLeftSideViewController {
  11. func applySearchTableHeader(_ message: String) {
  12. self.findTableView.tableColumn(withIdentifier: kResultsColumnId)?.headerCell.stringValue = message
  13. self.findTableView.headerView?.needsDisplay = true
  14. self.groupedFindTableView.tableColumn(withIdentifier: _kRelevanceColumnId)?.headerCell.stringValue = message
  15. self.groupedFindTableView.headerView?.needsDisplay = true
  16. }
  17. func documentDidBeginFind() {
  18. // [leftSideController applySearchTableHeader:[NSLocalizedString(@"Searching", @"Message in search table header") stringByAppendingEllipsis]];
  19. self.applySearchTableHeader(KMLocalizedString("Searching", "Message in search table header"))
  20. self.searchResults = []
  21. self.groupSearchResults = []
  22. }
  23. func documentDidEndFind() {
  24. self.applySearchTableHeader(KMLocalizedString("\(self.searchResults.count) Results", "Message in search table header"))
  25. }
  26. func updateFindResultHighlightsForDirection(_ direction: NSWindow.SelectionDirection) {
  27. var findResults: [KMSearchMode] = []
  28. if self.findPaneState == .singular && self.findTableView.window != nil {
  29. findResults = self.searchResults
  30. } else if self.findPaneState == .grouped && self.groupedFindTableView.window != nil {
  31. findResults = self.groupSearchResults[self.groupedFindTableView.clickedRow].datas
  32. }
  33. if (findResults.count == 0) {
  34. self.listView?.setHighlightedSelections(nil)
  35. } else {
  36. if direction == .directSelection {
  37. self.searchResultIndex = 0
  38. } else if (direction == .selectingNext) {
  39. self.searchResultIndex += 1
  40. if self.searchResultIndex >= findResults.count {
  41. self.searchResultIndex = 0
  42. }
  43. } else if (direction == .selectingPrevious) {
  44. self.searchResultIndex -= 1
  45. if self.searchResultIndex < 0 {
  46. self.searchResultIndex = findResults.count-1
  47. }
  48. }
  49. let currentSel = findResults[self.searchResultIndex].selection
  50. if currentSel.hasCharacters() {
  51. let page = currentSel.safeFirstPage()
  52. var rect = NSZeroRect
  53. for model in findResults {
  54. if let data = page, model.selection.pages().contains(data) {
  55. rect = NSUnionRect(rect, model.selection.bounds(for: data))
  56. }
  57. }
  58. let FIND_RESULT_MARGIN = 50.0
  59. rect = NSIntersectionRect(NSInsetRect(rect, -FIND_RESULT_MARGIN, -FIND_RESULT_MARGIN), page?.bounds(for: .cropBox) ?? .zero)
  60. self.listView?.go(to: page)
  61. self.listView?.go(to: rect, on: page)
  62. }
  63. if self.findPaneState == .grouped && self.groupedFindTableView.window != nil {
  64. var sels: [CPDFSelection] = []
  65. for model in findResults {
  66. model.selection.setColor(NSColor(red: 236/255.0, green: 241/255.0, blue: 83/255.0, alpha: 0.5))
  67. sels.append(model.selection)
  68. // model.selection.setColor(.yellow)
  69. }
  70. self.listView?.setHighlightedSelections(sels)
  71. }
  72. if currentSel.hasCharacters() {
  73. let bColor = NSColor(red: 236/255.0, green: 241/255.0, blue: 83/255.0, alpha: 0.5)
  74. let color = NSColor(red: 219/255.0, green: 220/255.0, blue: 3/255.0, alpha: 0.5)
  75. self.listView?.setHighlight(currentSel, forBorderColor: .clear, fill: color, animated: true)
  76. self.listView?.go(to: currentSel, animated: true)
  77. self.listView?.setCurrentSelection(currentSel, animate: true)
  78. }
  79. let mode = self.listView?.toolMode ?? .none
  80. if mode == .moveToolMode || mode == .magnifyToolMode || mode == .selectToolMode {
  81. self.listView?.setCurrentSelection(nil, animate: false)
  82. }
  83. }
  84. }
  85. }
  86. // MARK: - Actions
  87. extension KMLeftSideViewController {
  88. // 显示搜索模块
  89. func showSearchMode(_ searchString: String = "") {
  90. if self.leftView.segmentedControl.selectedSegment == 4 {
  91. } else {
  92. self.leftView.segmentedControl.selectedSegment = 4
  93. }
  94. self.searchViewController.searchField.stringValue = searchString
  95. self.findTableView.reloadData()
  96. }
  97. func search_initSubViews() {
  98. self.findTableView.delegate = self
  99. self.findTableView.dataSource = self
  100. self.findTableView.botaDelegate = self
  101. self.findTableView.menu?.delegate = self
  102. self.findTableView.target = self
  103. self.findTableView.doubleAction = #selector(goToSelectedFindResults)
  104. self.groupedFindTableView.delegate = self
  105. self.groupedFindTableView.dataSource = self
  106. self.groupedFindTableView.botaDelegate = self
  107. self.groupedFindTableView.menu?.delegate = self
  108. self.groupedFindTableView.target = self
  109. self.groupedFindTableView.doubleAction = #selector(goToSelectedFindResults)
  110. }
  111. func search_initDefalutValue() {
  112. self.mwcFlags.wholeWordSearch = KMDataManager.ud_integer(forKey: SKWholeWordSearchKey)
  113. self.mwcFlags.caseInsensitiveSearch = KMDataManager.ud_integer(forKey: SKCaseInsensitiveSearchKey)
  114. self.findTableView.backgroundColor = KMAppearance.Layout.l0Color()
  115. self.groupedFindTableView.backgroundColor = KMAppearance.Layout.l0Color()
  116. self.findTableView.tableColumn(withIdentifier: kPageColumnId)?.headerCell.title = KMLocalizedString("Page", "Table header title")
  117. self.groupedFindTableView.tableColumn(withIdentifier: kPageColumnId)?.headerCell.title = KMLocalizedString("Page", "Table header title")
  118. (self.groupedFindTableView.tableColumn(withIdentifier: _kRelevanceColumnId)?.dataCell as? NSCell)?.isEnabled = false
  119. }
  120. public func refreshUIOfSeachListIfNeed() {
  121. if self.type.methodType != .Search {
  122. return
  123. }
  124. Task { @MainActor in
  125. if self.searchField.stringValue.isEmpty == false {
  126. self.search(self.searchField)
  127. }
  128. }
  129. }
  130. }
  131. // MARK: - Menu
  132. extension KMLeftSideViewController {
  133. @objc func addAnnotationsForSelections(_ sender: NSMenuItem) {
  134. guard let selections = sender.representedObject as? [CPDFSelection], selections.count > 0 else {
  135. return
  136. }
  137. for selection in selections {
  138. self.listView?.addAnnotation(with: CAnnotationType(rawValue: sender.tag) ?? .circle, selection: selection, page: selection.page, bounds: selection.bounds)
  139. }
  140. }
  141. @objc func selectSelections(_ sender: NSMenuItem) {
  142. guard let selections = sender.representedObject as? [CPDFSelection], selections.count > 0 else {
  143. return
  144. }
  145. self.listView?.currentSelection = CPDFSelection.selectionByAddingSelections(selections as NSArray)
  146. }
  147. @objc func toggleWholeWordSearch(_ sender: AnyObject?) {
  148. if self.mwcFlags.wholeWordSearch == 1 {
  149. self.mwcFlags.wholeWordSearch = 0
  150. } else {
  151. self.mwcFlags.wholeWordSearch = 1
  152. }
  153. if self.searchField.stringValue.isEmpty == false {
  154. self.search(self.searchField)
  155. }
  156. KMDataManager.ud_set(self.mwcFlags.wholeWordSearch, forKey: SKWholeWordSearchKey)
  157. }
  158. @objc func toggleCaseInsensitiveSearch(_ sender: AnyObject?) {
  159. if self.mwcFlags.caseInsensitiveSearch == 0 {
  160. self.mwcFlags.caseInsensitiveSearch = 1
  161. } else {
  162. self.mwcFlags.caseInsensitiveSearch = 0
  163. }
  164. if self.searchField.stringValue.isEmpty == false {
  165. self.search(self.searchField)
  166. }
  167. KMDataManager.ud_set(self.mwcFlags.caseInsensitiveSearch, forKey: SKCaseInsensitiveSearchKey)
  168. }
  169. @objc func goToSelectedFindResults(_ sender: AnyObject?) {
  170. guard let olView = sender as? NSTableView, olView.clickedRow != -1 else {
  171. NSSound.beep()
  172. return
  173. }
  174. self.updateFindResultHighlightsForDirection(.directSelection)
  175. }
  176. }