KMLeftSideViewController+Note.swift 40 KB

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