KMLeftSideViewController+Note.swift 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. //
  2. // KMLeftSideViewController+Note.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2023/12/23.
  6. //
  7. import Foundation
  8. extension KMLeftSideViewController.Key {
  9. static let noteAscendSortKey = "KMLeftSideViewAscendSortBoolKey"
  10. static let noteSortTypeKey = "KMLeftSideViewNoteSortTypeKey"
  11. static let noteTableColumn = "KMNoteOutlineViewTableColumnKey"
  12. static let noteFilterPage = "kKMNoteFilterAnnotationPageKey"
  13. static let noteFilterTime = "kKMNoteFilterAnnotationTimeKey"
  14. static let noteFilterAuther = "kKMNoteFilterAnnotationAutherKey"
  15. }
  16. // MARK: - Menu
  17. extension KMLeftSideViewController {
  18. func note_initSubViews() {
  19. self.noteSearchField.backgroundColor = KMAppearance.Layout.l_1Color()
  20. self.noteSearchField.wantsLayer = true
  21. self.noteSearchField.layer?.backgroundColor = KMAppearance.Layout.l_1Color().cgColor
  22. self.noteSearchField.layer?.borderWidth = 1.0
  23. self.noteMoreButton.target = self
  24. self.noteMoreButton.tag = 304
  25. self.noteMoreButton.action = #selector(leftSideViewMoreButtonAction)
  26. self.moreButtonLayer = KMButtonLayer()
  27. self.noteMoreButton.layer?.addSublayer(self.moreButtonLayer!)
  28. self.moreButtonLayer?.frame = CGRectMake(0, 0, CGRectGetWidth(self.noteMoreButton.bounds), CGRectGetHeight(self.noteMoreButton.bounds))
  29. self.noteFilterButton.target = self
  30. self.noteFilterButton.action = #selector(noteFilterAction)
  31. self.filterButtonLayer = NSView()
  32. self.noteFilterButton.addSubview(self.filterButtonLayer!)
  33. self.filterButtonLayer?.frame = CGRectMake(14, 2, 8, 8)
  34. self.noteDoneButton.action = #selector(leftSideViewDoneButtonAction)
  35. self.noteDoneButton.target = self
  36. self.noteDoneButton.tag = 311
  37. self.noteDoneButton.isHidden = true
  38. self.noteSearchField.delegate = self
  39. self.noteSearchField.isHidden = true
  40. self.noteSearchField.endEditCallBack = { [unowned self] isEndEdit in
  41. if (isEndEdit) {
  42. self.noteSearchField.isHidden = true
  43. self.noteSearchButton.isHidden = false
  44. self.noteTitleLabel.isHidden = false
  45. }
  46. }
  47. self.sortTypeBox.downCallback = { [unowned self] downEntered, mouseBox, _ in
  48. if (downEntered) {
  49. let menu = NSMenu()
  50. let timeItem = menu.addItem(title: KMLocalizedString("Time", nil), action: #selector(sortTypeAction), target: self)
  51. timeItem?.representedObject = self
  52. timeItem?.tag = 0
  53. let pageItem = menu.addItem(title: KMLocalizedString("Page", nil), action: #selector(sortTypeAction), target: self)
  54. pageItem?.representedObject = self
  55. timeItem?.tag = 1
  56. if (self.noteSortType == .time) {
  57. timeItem?.state = .on
  58. pageItem?.state = .off
  59. } else if (self.noteSortType == .page) {
  60. timeItem?.state = .off
  61. pageItem?.state = .on
  62. }
  63. menu.popUp(positioning: nil, at: CGPointMake(-10, 0), in: self.sortTypeBox)
  64. }
  65. }
  66. self.noteOutlineView.delegate = self
  67. self.noteOutlineView.dataSource = self
  68. self.noteOutlineView.botaDelegate = self
  69. self.noteOutlineView.botaDataSource = self
  70. self.noteOutlineView.noteDelegate = self
  71. self.noteOutlineView.menu = NSMenu()
  72. self.noteOutlineView.menu?.delegate = self
  73. self.noteOutlineView.typeSelectHelper = SKTypeSelectHelper(matchOption: .SKSubstringMatch)
  74. self.noteOutlineView.registerForDraggedTypes(NSColor.readableTypes(for: NSPasteboard(name: .drag)))
  75. self.noteOutlineView.target = self
  76. self.noteOutlineView.doubleAction = #selector(selectSelectedNote)
  77. }
  78. func note_initDefalutValue() {
  79. self.noteView.wantsLayer = true
  80. self.noteView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor
  81. let sud = UserDefaults.standard
  82. if let dict = sud.dictionary(forKey: Self.Key.noteTableColumn) {
  83. self.noteTypeDict = dict
  84. } else {
  85. self.noteTypeDict = [Self.Key.noteFilterPage : false,
  86. Self.Key.noteFilterTime : false,
  87. Self.Key.noteFilterAuther : false]
  88. sud.sync_setValue(self.noteTypeDict, forKey: Self.Key.noteTableColumn)
  89. }
  90. self.caseInsensitiveNoteSearch = sud.bool(forKey: SKCaseInsensitiveNoteSearchKey)
  91. self.isAscendSort = KMDataManager.ud_bool(forKey: Self.Key.noteAscendSortKey)
  92. self.noteTitleLabel.stringValue = KMLocalizedString("Notes", nil);
  93. self.noteTitleLabel.textColor = KMAppearance.Layout.h0Color()
  94. self.noteSearchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor
  95. self.noteMoreButton.wantsLayer = true
  96. self.moreButtonLayer?.layerType = .none
  97. self.moreButtonLayer?.isHidden = true
  98. self.noteFilterButton.toolTip = KMLocalizedString("Sort", nil)
  99. self.noteFilterButton.wantsLayer = true
  100. self.filterButtonLayer?.isHidden = true
  101. self.filterButtonLayer?.wantsLayer = true
  102. self.filterButtonLayer?.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
  103. self.filterButtonLayer?.layer?.cornerRadius = 4.0
  104. if (self.isAscendSort) {
  105. self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankReverse)
  106. self.noteSortButton.toolTip = KMLocalizedString("ascending sort", nil)
  107. } else {
  108. self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankPositive)
  109. self.noteSortButton.toolTip = KMLocalizedString("descending sort", nil)
  110. }
  111. self.noteSearchButton.toolTip = KMLocalizedString("Search", nil)
  112. self.noteDoneButton.title = KMLocalizedString("Done", nil)
  113. self.noteDoneButton.toolTip = KMLocalizedString("Done", nil)
  114. self.noteDoneButton.setTitleColor(KMAppearance.Layout.w0Color())
  115. self.noteDoneButton.wantsLayer = true
  116. self.noteDoneButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
  117. self.noteDoneButton.layer?.cornerRadius = 4.0
  118. self.noteHeaderView.wantsLayer = true
  119. self.noteHeaderView.layer?.backgroundColor = KMAppearance.Else.textTagColor().cgColor
  120. self.noteHeaderView.layer?.cornerRadius = 1.0
  121. let sortType = KMDataManager.ud_integer(forKey: Self.Key.noteSortTypeKey)
  122. if (sortType == 1) {
  123. self.noteSortType = KMNoteSortType(rawValue: sortType) ?? .none
  124. if (self.noteSortType == .time) {
  125. self.sortTypeLabel.stringValue = KMLocalizedString("Time", nil)
  126. self.sortTypeBox.toolTip = KMLocalizedString("Time", nil)
  127. } else if (self.noteSortType == .page) {
  128. self.sortTypeLabel.stringValue = KMLocalizedString("Page", nil)
  129. self.sortTypeBox.toolTip = KMLocalizedString("Page", nil)
  130. }
  131. } else {
  132. self.noteSortType = .time
  133. self.sortTypeLabel.stringValue = KMLocalizedString("Time", nil)
  134. }
  135. self.sortTypeLabel.textColor = KMAppearance.Layout.h1Color()
  136. self.noteOutlineView.backgroundColor = KMAppearance.Layout.l0Color()
  137. self.noteOutlineView.autoresizesOutlineColumn = false
  138. self.noteOutlineView.indentationPerLevel = 0
  139. }
  140. @IBAction func note_expandAllComments(_ sender: AnyObject?) {
  141. if (self.foldType == .unfold) { // 已全部展开
  142. return
  143. }
  144. // 设置全部展开的标识
  145. self.foldType = .unfold
  146. // 加载数据
  147. self.loadUnfoldDate(.none)
  148. // 刷新UI
  149. self.noteOutlineView.reloadData()
  150. }
  151. @IBAction func note_foldAllComments(_ sender: AnyObject?) {
  152. if (self.foldType == .fold) {
  153. return
  154. }
  155. self.foldType = .fold
  156. self.loadUnfoldDate(.none)
  157. self.noteOutlineView.reloadData()
  158. }
  159. @IBAction func noteShowNoteAction(_ sender: AnyObject?) {
  160. let item = sender as? NSMenuItem
  161. let tag = item?.tag ?? 0
  162. if (tag == 100) {
  163. } else if (tag == 101) {
  164. let isPage = self.noteTypeDict[Self.Key.noteFilterPage] as? Bool ?? false
  165. self.noteTypeDict[Self.Key.noteFilterPage] = !isPage
  166. } else if (tag == 102) {
  167. let isTime = self.noteTypeDict[Self.Key.noteFilterTime] as? Bool ?? false
  168. self.noteTypeDict[Self.Key.noteFilterTime] = !isTime
  169. } else if (tag == 103) {
  170. let isAuther = self.noteTypeDict[Self.Key.noteFilterAuther] as? Bool ?? false
  171. self.noteTypeDict[Self.Key.noteFilterAuther] = !isAuther
  172. }
  173. UserDefaults.standard.sync_setValue(self.noteTypeDict, forKey: Self.Key.noteTableColumn)
  174. let selectRow = self.noteOutlineView.selectedRow
  175. self.noteOutlineView.reloadData()
  176. self.noteOutlineView.selectRowIndexes(IndexSet(integer: selectRow), byExtendingSelection: false)
  177. }
  178. @objc func exportAnnotationNotes(_ sender: AnyObject?) {
  179. let doc = self.view.window?.windowController?.document as? NSDocument
  180. doc?.saveTo(sender)
  181. }
  182. @objc func leftSideEmptyAnnotationClick_DeleteAnnotation(_ sender: AnyObject?) {
  183. guard let doc = self.listView.document else {
  184. return
  185. }
  186. Task {
  187. let response = await KMAlertTool.runModel(message: KMLocalizedString("This will permanently remove all annotations. Are you sure to continue?", nil), buttons: [KMLocalizedString("Yes", nil), KMLocalizedString("No", nil)])
  188. if response == .alertFirstButtonReturn {
  189. var annos: [CPDFAnnotation] = []
  190. for i in 0 ..< doc.pageCount {
  191. let page = self.listView.document.page(at: i)
  192. for anno in page?.annotations ?? [] {
  193. if anno is CPDFTextWidgetAnnotation || anno is CPDFButtonWidgetAnnotation || anno is CPDFChoiceWidgetAnnotation {
  194. continue
  195. }
  196. // if ([annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeSignature]) {
  197. // continue;
  198. // }
  199. annos.append(anno)
  200. }
  201. }
  202. for anno in annos {
  203. self.listView.remove(anno)
  204. }
  205. self.reloadAnnotation()
  206. }
  207. }
  208. }
  209. @objc func unfoldNoteAction(_ sender: NSMenuItem) {
  210. if sender.state == .on {
  211. return
  212. }
  213. let row = self.noteOutlineView.clickedRow
  214. guard let foldNote = self.fetchNote(for: row) else {
  215. return
  216. }
  217. if self.allFoldNotes.contains(foldNote) == false {
  218. self.allFoldNotes.append(foldNote)
  219. }
  220. if self.allFoldNotes.count == self.canFoldNotes.count {
  221. self.foldType = .unfold
  222. } else {
  223. self.foldType = .none
  224. }
  225. let viewS = self.noteOutlineView.view(atColumn: 0, row: row, makeIfNecessary: true)
  226. (viewS as? KMNoteTableViewCell)?.isFold = false
  227. }
  228. @objc func foldNoteAction(_ sender: NSMenuItem) {
  229. // if sender.state == .on {
  230. // return
  231. // }
  232. let row = self.noteOutlineView.clickedRow
  233. guard let foldNote = self.fetchNote(for: row) else {
  234. return
  235. }
  236. if self.allFoldNotes.contains(foldNote) == false {
  237. self.allFoldNotes.append(foldNote)
  238. }
  239. if (self.allFoldNotes.count == 0) {
  240. self.foldType = .fold
  241. } else {
  242. self.foldType = .none
  243. }
  244. let viewS = self.noteOutlineView.view(atColumn: 0, row: row, makeIfNecessary: true)
  245. (viewS as? KMNoteTableViewCell)?.isFold = true
  246. }
  247. @objc func deleteNotes(_ sender: NSMenuItem) {
  248. self.outlineView(self.noteOutlineView, deleteItems: sender.representedObject as? [Any] ?? [])
  249. }
  250. @objc func removeAllAnnotations(_ sender: AnyObject?) {
  251. self.leftSideEmptyAnnotationClick_DeleteAnnotation(nil)
  252. }
  253. @objc func editNoteTextFromTable(_ sender: NSMenuItem) {
  254. // PDFAnnotation *annotation = [sender representedObject];
  255. guard let annotation = sender.representedObject as? CPDFAnnotation else {
  256. return
  257. }
  258. self.listView.scrollAnnotationToVisible(annotation)
  259. // self.listView.activeAnnotation = annotation
  260. // [self showNote:annotation];
  261. // SKNoteWindowController *noteController = (SKNoteWindowController *)[self windowControllerForNote:annotation];
  262. // [[noteController window] makeFirstResponder:[noteController textView]];
  263. // [[noteController textView] selectAll:nil];
  264. }
  265. @objc func editThisAnnotation(_ sender: AnyObject?) {
  266. KMPrint("editThisAnnotation ...")
  267. }
  268. @objc func editNoteFromTable(_ sender: AnyObject?) {
  269. KMPrint("editNoteFromTable ...")
  270. }
  271. @IBAction func noteSortAction(_ sender: AnyObject?) {
  272. if (self.isAscendSort) {
  273. self.isAscendSort = false
  274. self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankPositive)
  275. self.noteSortButton.toolTip = KMLocalizedString("descending sort", nil)
  276. } else {
  277. self.isAscendSort = true
  278. self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankReverse)
  279. self.noteSortButton.toolTip = KMLocalizedString("ascending sort", nil)
  280. }
  281. KMDataManager.ud_set(self.isAscendSort, forKey: Self.Key.noteAscendSortKey)
  282. // self.annotationSort(sortArray: [])
  283. self.reloadAnnotation()
  284. }
  285. @IBAction func noteSearchAction(_ sender: NSButton) {
  286. self.noteSearchField.isHidden = false
  287. self.noteTitleLabel.isHidden = true
  288. self.noteSearchButton.isHidden = true
  289. self.noteDoneButton.isHidden = false
  290. self.noteFilterButton.isHidden = true
  291. self.noteMoreButton.isHidden = true
  292. self.noteSearchField.becomeFirstResponder()
  293. }
  294. @IBAction func noteFilterAction(_ sender: AnyObject?) {
  295. let button = sender as? NSButton
  296. let menu = NSMenu()
  297. let filterViewController = KMNoteOutlineFilterViewController()
  298. filterViewController.listView = self.listView
  299. filterViewController.view.layer?.backgroundColor = .clear
  300. var notes = NSMutableArray()
  301. // for section in self._annotations {
  302. // if section.annotations?.count != 0 {
  303. // for item in section.annotations! {
  304. // notes.add(item.annotation!)
  305. // }
  306. // }
  307. // }
  308. filterViewController.setNotesArray(self.allAnnotations as NSArray)
  309. filterViewController.applyFilterCallback = { [weak self] typeArr, colorArr, authorArr, isEmpty in
  310. menu.cancelTracking()
  311. if (isEmpty) {
  312. self?.filterButtonLayer?.isHidden = true
  313. } else {
  314. self?.filterButtonLayer?.isHidden = false
  315. }
  316. self?.reloadAnnotation()
  317. }
  318. filterViewController.cancelCallback = { isCancel in
  319. if (isCancel) {
  320. menu.cancelTracking()
  321. }
  322. }
  323. let item = menu.addItem(withTitle: "", action: nil, keyEquivalent: "")
  324. item.target = self
  325. item.representedObject = filterViewController
  326. item.view = filterViewController.view
  327. menu.popUp(positioning: nil, at: CGPointMake(-130, 30), in: button)
  328. }
  329. func fetchNote(for index: Int) -> CPDFAnnotation? {
  330. if self.noteSearchMode { // 搜索模式
  331. return self.noteSearchArray.safe_element(for: index) as? CPDFAnnotation
  332. } else { // 常规模式(非搜索)
  333. let section = self.annotations.safe_element(for: index) as? KMBOTAAnnotationSection
  334. return section?.annotations?.first?.annotation
  335. }
  336. }
  337. @IBAction @objc func sortTypeAction(_ sender: NSMenuItem) {
  338. let item = sender
  339. let tag = item.tag
  340. if (item.state == .on) {
  341. item.state = .off
  342. } else {
  343. item.state = .on
  344. }
  345. if (tag == 0) {
  346. self.noteSortType = .page
  347. self.sortTypeLabel.stringValue = KMLocalizedString("Page", nil)
  348. self.sortTypeBox.toolTip = KMLocalizedString("Page", nil)
  349. } else if (tag == 1) {
  350. self.noteSortType = .time
  351. self.sortTypeLabel.stringValue = KMLocalizedString("Time", nil)
  352. self.sortTypeBox.toolTip = KMLocalizedString("Time", nil)
  353. }
  354. KMDataManager.ud_set(self.noteSortType.rawValue, forKey: Self.Key.noteSortTypeKey)
  355. // self.annotationSort(sortArray: [])
  356. self.reloadAnnotation()
  357. }
  358. }
  359. // MARK: - Note
  360. extension KMLeftSideViewController {
  361. // func loadAnnotationSortData(_ morePredicates: NSArray) {
  362. // var isLink = false
  363. // var typeMutableArr = NSMutableArray()
  364. // if self.allAnnotations.count > 0 {
  365. // for annotation in self.allAnnotations {
  366. // if annotation is CPDFLinkAnnotation || annotation is CPDFTextWidgetAnnotation || annotation is CPDFButtonWidgetAnnotation || annotation is CPDFChoiceWidgetAnnotation {
  367. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeSignature] ||
  368. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeText] ||
  369. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeButton] ||
  370. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeChoice]) {
  371. // isLink = true
  372. // } else {
  373. // if typeMutableArr.contains(annotation.type) == false {
  374. // typeMutableArr.add(annotation.type)
  375. // }
  376. // }
  377. // }
  378. // }
  379. //
  380. // var colorMutableArray = NSMutableArray()
  381. // var typeMutableArray = NSMutableArray()
  382. // var authorMutableArray = NSMutableArray()
  383. // for annotation in self.allAnnotations {
  384. // if annotation is CPDFLinkAnnotation || annotation is CPDFTextWidgetAnnotation || annotation is CPDFButtonWidgetAnnotation || annotation is CPDFChoiceWidgetAnnotation {
  385. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeSignature] ||
  386. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeText] ||
  387. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeButton] ||
  388. //// [annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeChoice]) {
  389. // let noteColor = annotation.color ?? .clear
  390. // let noteType = annotation.type ?? ""
  391. // let authorString = annotation.userName() ?? ""
  392. // if (noteColor != nil) {
  393. // if (colorMutableArray.count > 0) {
  394. // if colorMutableArray.contains(noteColor) == false {
  395. // colorMutableArray.add(noteColor)
  396. // }
  397. // } else {
  398. // colorMutableArray.add(noteColor)
  399. // }
  400. // }
  401. // if noteType.isEmpty == false {
  402. // if typeMutableArray.count > 0 {
  403. // if typeMutableArray.contains(noteType) == false {
  404. // typeMutableArray.add(noteType)
  405. // }
  406. // } else {
  407. // typeMutableArray.add(noteType)
  408. // }
  409. // }
  410. // if authorString.isEmpty == false {
  411. // if authorString.count > 0 {
  412. // if authorMutableArray.contains(authorString) == false {
  413. // authorMutableArray.add(authorString)
  414. // }
  415. // } else {
  416. // authorMutableArray.add(authorString)
  417. // }
  418. // }
  419. // } else {
  420. // if typeMutableArr.contains(annotation.type) == false {
  421. // typeMutableArr.add(annotation.type)
  422. // }
  423. // }
  424. // }
  425. //
  426. // let sud = UserDefaults.standard
  427. // var typeArr = NSMutableArray()
  428. //
  429. // if let typeData = KMDataManager.ud_object(forKey: NoteFilterVC.filterSelectTypeKey) as? Data {
  430. // if let data = NSKeyedUnarchiver.unarchiveObject(with: typeData) as? NSArray {
  431. // typeArr = NSMutableArray(array: data)
  432. // }
  433. // }
  434. // var colorArr = NSMutableArray()
  435. // if let colorData = sud.object(forKey: NoteFilterVC.filterSelectColorKey) as? Data {
  436. // if let data = NSKeyedUnarchiver.unarchiveObject(with: colorData) as? NSArray {
  437. // colorArr = NSMutableArray(array: data)
  438. // }
  439. // }
  440. // var authorArr = NSMutableArray()
  441. // if let authorData = sud.object(forKey: NoteFilterVC.filterSelectAuthorKey) as? Data {
  442. // if let data = NSKeyedUnarchiver.unarchiveObject(with: authorData) as? NSArray {
  443. // authorArr = NSMutableArray(array: data)
  444. // }
  445. // }
  446. //
  447. // var temporaryArr1 = NSMutableArray()
  448. // var temporaryArr2 = NSMutableArray()
  449. // var temporaryArr3 = NSMutableArray()
  450. // if (typeArr.count > 0) {
  451. // for type in typeArr {
  452. // if typeMutableArray.contains(type) == false {
  453. // temporaryArr1.add(type)
  454. // }
  455. // }
  456. // }
  457. // if (colorArr.count > 0) {
  458. // for color in colorArr {
  459. // if colorMutableArray.contains(color) == false {
  460. // temporaryArr2.add(color)
  461. // }
  462. // }
  463. // }
  464. // if (authorArr.count > 0) {
  465. // for author in authorArr {
  466. // if authorMutableArray.contains(author) == false {
  467. // temporaryArr3.add(author)
  468. // }
  469. // }
  470. // }
  471. //
  472. // if (temporaryArr1.count > 0) {
  473. // for type in temporaryArr1 {
  474. // typeArr.remove(type)
  475. // }
  476. // }
  477. // if (temporaryArr2.count > 0) {
  478. // for color in temporaryArr2 {
  479. // colorArr.remove(color)
  480. // }
  481. // }
  482. // if (temporaryArr3.count > 0) {
  483. // for author in temporaryArr3 {
  484. // authorArr.remove(author)
  485. // }
  486. // }
  487. //
  488. // var predicateMutableArr = NSMutableArray()
  489. // }
  490. func note_refrshUIIfNeed() {
  491. if self.type.methodType != .Annotation {
  492. return
  493. }
  494. Task { @MainActor in
  495. self.noteOutlineView.reloadData()
  496. }
  497. }
  498. func note_reloadDataIfNeed() {
  499. if self.type.methodType != .Annotation {
  500. return
  501. }
  502. self.reloadAnnotation()
  503. }
  504. func note_reloadDataForAnnoIfNeed(anno: CPDFAnnotation) {
  505. if self.type.methodType != .Annotation {
  506. return
  507. }
  508. if anno is CPDFLineAnnotation || anno is CPDFSquareAnnotation || anno is CPDFCircleAnnotation || anno is CPDFInkAnnotation {
  509. // 形状注释 + Ink 需要显示框住的内容【刷新】
  510. for item in self.annotations {
  511. if let data = item.annotations?.first?.annotation, data.isEqual(to: anno) {
  512. self.noteOutlineView.reloadItem(item.annotations?.first)
  513. break
  514. }
  515. }
  516. }
  517. }
  518. func reloadAnnotation() {
  519. if self.listView != nil {
  520. let filterKey = self.listView?.document?.documentURL.path ?? ""
  521. var typeArr: [Any] = KMBotaTools.noteFilterAnnoTypes(key: filterKey)
  522. var colorArr: [Any] = KMBotaTools.noteFilterColors(key: filterKey)
  523. var authorArr: [Any] = KMBotaTools.noteFilterAuthors(key: filterKey)
  524. if typeArr.count == 0 && colorArr.count == 0 && authorArr.count == 0 {
  525. // self.filtrateButton.image = NSImage(named: "KMImageNameAnnotationsFiltrate")
  526. self.filterButtonLayer?.isHidden = true
  527. } else {
  528. // self.filtrateButton.image = NSImage(named: "icon_annotation_screening_select")self.filterButtonLayer?.isHidden = true
  529. self.filterButtonLayer?.isHidden = false
  530. }
  531. var dataArray: [KMBOTAAnnotationSection] = []
  532. var annotationArray: [CPDFAnnotation] = []
  533. var allAnnotation: [CPDFAnnotation] = []
  534. for i in 0 ..< self.listView.document.pageCount {
  535. var items: [KMBOTAAnnotationItem] = []
  536. let page = self.listView.document.page(at: i)
  537. var annos: [CPDFAnnotation] = []
  538. // 处理过滤
  539. if typeArr.count == 0 && colorArr.count == 0 && authorArr.count == 0 {
  540. let types = ["Highlight","Underline","Strikeout","Freehand","FreeText","Note","Square","Circle","Line","Stamp","Arrow","Image","Redact","Sign"]
  541. annos = KMOCToolClass.filterAnnotation(annotations: page?.annotations ?? [],types: types) as? [CPDFAnnotation] ?? []
  542. } else {
  543. var filterAnnos: [CPDFAnnotation] = page?.annotations ?? []
  544. if typeArr.count > 0 {
  545. filterAnnos = (KMOCToolClass.filterAnnotation(annotations: filterAnnos, types: typeArr) as? [CPDFAnnotation]) ?? []
  546. }
  547. if (colorArr.count > 0) {
  548. filterAnnos = (KMOCToolClass.filterAnnotation(annotations: filterAnnos,colors: colorArr) as? [CPDFAnnotation]) ?? []
  549. }
  550. if (authorArr.count > 0) {
  551. filterAnnos = (KMOCToolClass.filterAnnotation(annotations: filterAnnos,authors: authorArr) as? [CPDFAnnotation]) ?? []
  552. }
  553. annos = filterAnnos
  554. }
  555. //添加签名注释
  556. for annotation in page?.annotations ?? [] {
  557. if annotation.isKind(of: CPDFSignatureAnnotation.self) {
  558. annos.append(annotation)
  559. }
  560. }
  561. for annotation in annos {
  562. if annotation.annotationShouldDisplay() == false {
  563. annos.removeObject(annotation)
  564. }
  565. }
  566. //转换所有annotation类型
  567. let section = KMBOTAAnnotationSection()
  568. for anno in annos {
  569. let item = KMBOTAAnnotationItem()
  570. item.section = section
  571. item.annotation = anno
  572. item.index = Int(anno.page.pageIndex())
  573. items.append(item)
  574. allAnnotation.append(anno)
  575. }
  576. if items.count != 0 {
  577. section.annotations = items
  578. section.page = page
  579. section.isItemExpanded = true
  580. dataArray.append(section)
  581. }
  582. //添加所有annotation 用于筛选
  583. annotationArray += (page?.annotations ?? [])
  584. }
  585. // 处理排序
  586. if self.noteSortType == .page {
  587. var datas: [KMBOTAAnnotationSection] = []
  588. /// 排序(升序)
  589. if self.isAscendSort {
  590. allAnnotation.sort {
  591. let idx0 = $0.page?.pageIndex() ?? 0
  592. let idx1 = $1.page?.pageIndex() ?? 0
  593. return idx0 <= idx1
  594. }
  595. } else {
  596. allAnnotation.sort {
  597. let idx0 = $0.page?.pageIndex() ?? 0
  598. let idx1 = $1.page?.pageIndex() ?? 0
  599. return idx0 > idx1
  600. }
  601. }
  602. for anno in allAnnotation {
  603. let section = KMBOTAAnnotationSection()
  604. let item = KMBOTAAnnotationItem()
  605. item.section = section
  606. item.annotation = anno
  607. item.index = Int(anno.pageIndex())
  608. section.annotations = [item]
  609. section.page = anno.page
  610. section.isItemExpanded = true
  611. datas.append(section)
  612. }
  613. self.annotations = datas
  614. } else if self.noteSortType == .time {
  615. var datas: [KMBOTAAnnotationSection] = []
  616. /// 排序(升序)
  617. if self.isAscendSort {
  618. allAnnotation.sort {
  619. if $0.modificationDate() == nil {
  620. return false
  621. }
  622. if $1.modificationDate() == nil {
  623. return false
  624. }
  625. return $0.modificationDate() <= $1.modificationDate()
  626. }
  627. } else {
  628. allAnnotation.sort {
  629. if $0.modificationDate() == nil {
  630. return false
  631. }
  632. if $1.modificationDate() == nil {
  633. return false
  634. }
  635. return $0.modificationDate() > $1.modificationDate()
  636. }
  637. }
  638. for anno in allAnnotation {
  639. let section = KMBOTAAnnotationSection()
  640. let item = KMBOTAAnnotationItem()
  641. item.section = section
  642. item.annotation = anno
  643. item.index = Int(anno.pageIndex())
  644. section.annotations = [item]
  645. section.page = anno.page
  646. section.isItemExpanded = true
  647. datas.append(section)
  648. }
  649. self.annotations = datas
  650. }
  651. // 转换对象,用于数据显示
  652. self.allAnnotations = annotationArray
  653. // if self.annotations.count < 1 {
  654. // self.filtrateButton.isEnabled = false
  655. // } else {
  656. // self.filtrateButton.isEnabled = true
  657. // }
  658. }
  659. Task { @MainActor in
  660. self.noteOutlineView.reloadData()
  661. }
  662. }
  663. // 搜索 Action
  664. func updateNoteFilterPredicate() {
  665. var stringValue = self.noteSearchField.stringValue
  666. if self.caseInsensitiveNoteSearch { // 忽略大小写
  667. stringValue = stringValue.lowercased()
  668. }
  669. // 清空数据
  670. self.noteSearchArray.removeAll()
  671. if stringValue.isEmpty {
  672. for section in self.annotations {
  673. guard let note = section.annotations?.first?.annotation else {
  674. continue
  675. }
  676. self.noteSearchArray.append(note)
  677. }
  678. } else {
  679. for section in self.annotations {
  680. guard let note = section.annotations?.first?.annotation else {
  681. continue
  682. }
  683. var noteString = KMBOTAAnnotationTool.fetchContentLabelString(annotation: note)
  684. if let anno = note as? CPDFMarkupAnnotation {
  685. noteString = anno.markupContent()
  686. }
  687. if self.caseInsensitiveNoteSearch {
  688. noteString = noteString.lowercased()
  689. }
  690. if noteString.contains(stringValue) {
  691. self.noteSearchArray.append(note)
  692. }
  693. }
  694. }
  695. // 刷新 UI
  696. Task { @MainActor in
  697. self.noteOutlineView.reloadData()
  698. }
  699. }
  700. @objc func selectSelectedNote(_ sender: AnyObject?) {
  701. if self.listView.hideNotes == false {
  702. let selectedNotes = self.selectedNotes()
  703. if selectedNotes.count == 1 {
  704. let annotation = selectedNotes.last!
  705. self.listView.go(to: annotation.bounds, on: annotation.page, animated: true)
  706. // [pdfView scrollAnnotationToVisible:annotation];
  707. // [pdfView setActiveAnnotation:annotation];
  708. self.listView.updateActiveAnnotations([annotation])
  709. self.listView.setNeedsDisplayAnnotationViewForVisiblePages()
  710. // }
  711. }
  712. // NSInteger column = [sender clickedColumn];
  713. // if (column != -1) {
  714. // NSString *colID = [[[sender tableColumns] objectAtIndex:column] identifier];
  715. //
  716. // if ([colID isEqualToString:@"color"]){
  717. // for (PDFAnnotation *annotation in self.pdfView.activeAnnotations) {
  718. // if (![annotation isKindOfClass:[PDFAnnotationChoiceWidget class]] &&
  719. // ![annotation isKindOfClass:[PDFAnnotationButtonWidget class]] &&
  720. // ![annotation isKindOfClass:[PDFAnnotationTextWidget class]]) {
  721. // [[NSColorPanel sharedColorPanel] orderFront:nil];
  722. // break;
  723. // }
  724. //
  725. // }
  726. // }
  727. // }
  728. }
  729. }
  730. func selectedNotes() -> [CPDFAnnotation] {
  731. var selectedNotes: [CPDFAnnotation] = []
  732. let rowIndexes = self.noteOutlineView.selectedRowIndexes
  733. for row in rowIndexes {
  734. let item = self.noteOutlineView.item(atRow: row)
  735. if item is KMBOTAAnnotationItem {
  736. if let anno = (item as! KMBOTAAnnotationItem).annotation {
  737. // if anno.type == nil {
  738. // item = [(SKNoteText *)item note];
  739. // }
  740. if selectedNotes.contains(anno) == false {
  741. selectedNotes.append(anno)
  742. }
  743. }
  744. }
  745. }
  746. return selectedNotes
  747. }
  748. func clearAnnotationFilterData() {
  749. if let _key = self.listView?.document?.documentURL?.path {
  750. let userDefaults = UserDefaults.standard
  751. let typeData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false)
  752. userDefaults.set(typeData, forKey: NoteFilterVC.filterSelectTypeKey + _key)
  753. let colorData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false)
  754. userDefaults.set(colorData, forKey: NoteFilterVC.filterSelectColorKey + _key)
  755. let authorData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false)
  756. userDefaults.set(authorData, forKey: NoteFilterVC.filterSelectAuthorKey + _key)
  757. userDefaults.synchronize()
  758. }
  759. }
  760. }