KMBookMarkViewController.swift 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. //
  2. // KMBookMarkViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lxy on 2022/10/10.
  6. //
  7. import Cocoa
  8. import PDFKit
  9. typealias KMBookMarkViewControllerBookMarkDidChange = (_ controller: KMBookMarkViewController, _ bookMarks: [KMBookMarkItem]) -> Void
  10. @objc protocol KMBookMarkViewControllerDelegate: NSObjectProtocol {
  11. @objc optional func bkControllerAddAction(controller: KMBookMarkViewController)
  12. }
  13. class KMBookMarkViewController: KMNBaseViewController {
  14. @IBOutlet weak var addBookButton: NSButton!
  15. @IBOutlet weak var titleTextField: NSTextField!
  16. @IBOutlet weak var sortButton: NSButton!
  17. @IBOutlet var topSeplineView: NSView!
  18. @IBOutlet weak var bookTableView: NSTableView!
  19. @IBOutlet weak var emptyView: NSView!
  20. @IBOutlet weak var bigTipLabel: NSTextField!
  21. @IBOutlet weak var tipLabel: NSTextField!
  22. var dataSource: [KMBookMarkItem]!
  23. var renameTextField: NSTextField!
  24. var renamePDFBook: KMBookMarkItem!
  25. var renameCellView: KMBookCellView!
  26. // var listView: CPDFListView!
  27. weak var document: CPDFDocument?
  28. var isLocalEvent: Bool = false //区分外部点击还是内部点击
  29. var selectItems: [KMBookMarkItem] = []
  30. var bookMarkDidChange: KMBookMarkViewControllerBookMarkDidChange?
  31. weak var delegate: KMBookMarkViewControllerDelegate?
  32. var handdler: KMNBookmarkHanddler?
  33. // 升序
  34. private var sortType_: KMSortMode = .ascending
  35. convenience init() {
  36. self.init(nibName: "KMBookMarkViewController", bundle: nil)
  37. }
  38. override func viewWillAppear() {
  39. super.viewWillAppear()
  40. self.interfaceThemeDidChanged(NSApp.appearance?.name ?? .aqua)
  41. }
  42. override func viewDidLoad() {
  43. super.viewDidLoad()
  44. self.topSeplineView.wantsLayer = true
  45. self.topSeplineView.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.1).cgColor
  46. self.bookTableView.style = NSTableView.Style.plain
  47. self.bookTableView.allowsMultipleSelection = true
  48. self.bookTableView.doubleAction = #selector(renameBookAction)
  49. // self.bookTableView.selectionHighlightStyle = NSTableView.SelectionHighlightStyle.none;
  50. self.sortButton.target = self
  51. self.sortButton.action = #selector(sortAction)
  52. self.refreshUI()
  53. self.reloadData()
  54. }
  55. func refreshUI() {
  56. self.titleTextField.font = NSFont.SFProTextSemiboldFont(14.0)
  57. // self.titleTextField.textColor = NSColor.km_init(hex: "#252629")
  58. self.titleTextField.stringValue = NSLocalizedString("Bookmarks", comment: "")
  59. // self.addBookButton.toolTip = NSLocalizedString("Add Bookmark", comment: "")
  60. self.addBookButton.image = NSImage(named: "KMImageNameBotaBookmarkMoreIcon")
  61. self.sortButton.image = NSImage(named: "KMImageNameBotaBookmarkSortIcon")
  62. self.bigTipLabel.font = NSFont.SFProTextRegularFont(14.0)
  63. self.bigTipLabel.textColor = NSColor.km_init(hex: "#616469")
  64. self.bigTipLabel.stringValue = NSLocalizedString("No Bookmarks", comment: "")
  65. let title = NSLocalizedString("To create a bookmark, please right-click on the selected page and choose \"Add Bookmark\", or click \"Add\" button in the upper right corner.", comment: "")
  66. let paragraphStyle = NSMutableParagraphStyle()
  67. paragraphStyle.lineHeightMultiple = 1.32
  68. paragraphStyle.alignment = .center
  69. self.tipLabel.attributedStringValue = NSMutableAttributedString(string: title, attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle, .foregroundColor : NSColor.km_init(hex: "#94989C")])
  70. self.tipLabel.isHidden = true
  71. }
  72. func reloadData() {
  73. let array = document?.bookmarks() ?? [CPDFBookmark]()
  74. var bookMarks: [KMBookMarkItem] = []
  75. for bookMark in array {
  76. let item = KMBookMarkItem()
  77. item.bookMark = bookMark
  78. item.index = UInt(bookMark.pageIndex)
  79. item.label = bookMark.label
  80. bookMarks.append(item)
  81. }
  82. self.dataSource = bookMarks
  83. if self.sortType_ == .descending {
  84. self.dataSource.sort(){$0.bookMark.pageIndex >= $1.bookMark.pageIndex}
  85. } else {
  86. self.dataSource.sort(){$0.bookMark.pageIndex < $1.bookMark.pageIndex}
  87. }
  88. self.bookTableView.reloadData()
  89. self.updateAddBookMarkState()
  90. }
  91. func addBookMarkAndEdit(newBookMark: KMBookMarkItem) {
  92. _ = self.dataSource.contains { KMBookMarkItem in
  93. if KMBookMarkItem.bookMark == newBookMark.bookMark {
  94. let index = KMOCToolClass.arrayIndexOf(array: self.dataSource, item: KMBookMarkItem) ?? 0
  95. self.didSelectItem(row: index, event: NSEvent())
  96. self.renameBookWithRow(row: index)
  97. return true
  98. }
  99. return false
  100. }
  101. }
  102. override func addNotifations() {
  103. super.addNotifations()
  104. NotificationCenter.default.addObserver(self, selector: #selector(KMPDFViewCurrentPageDidChangedNotification), name: NSNotification.Name.init(rawValue: "KMPDFViewCurrentPageDidChanged"), object: nil)
  105. NotificationCenter.default.addObserver(self, selector: #selector(documentPageCountChangedNotification), name: NSNotification.Name.init(rawValue: "CPDFDocumentPageCountChangedNotification"), object: nil)
  106. }
  107. private func addMenuTitle(view: NSView, event: NSEvent) {
  108. let menus : NSMenu = NSMenu(title: "")
  109. menus.delegate = self
  110. let addItem = self.menuItemWithTitle(title: NSLocalizedString("Rename", comment: ""), action: #selector(renameBookAction))
  111. let addChildItem = self.menuItemWithTitle(title: NSLocalizedString("Change Destination", comment: ""), action: #selector(changeLocationAction))
  112. let addHigherItem = self.menuItemWithTitle(title: NSLocalizedString("Delete", comment: ""), action: #selector(deleteBookAction))
  113. menus.addItem(addItem)
  114. menus.addItem(addChildItem)
  115. menus.addItem(addHigherItem)
  116. let point = view.convert(event.locationInWindow, from: nil)
  117. menus.popUp(positioning: nil, at: point, in: view)
  118. // self.bookTableView.menu = menus
  119. }
  120. func menuItemWithTitle(title:String, action:Selector?) -> NSMenuItem {
  121. let menuItem = NSMenuItem.init(title: title as String, action: action, keyEquivalent: "")
  122. menuItem.target = self
  123. return menuItem
  124. }
  125. //MARK: Menu Action
  126. @objc func renameBookAction() {
  127. if self.bookTableView.selectedRowIndexes.count == 1 {
  128. self.renameBookWithRow(row: self.bookTableView.selectedRowIndexes.first!)
  129. } else {
  130. __NSBeep()
  131. }
  132. }
  133. @IBAction func escButtonAction(_ sender: Any) {
  134. self.bookTableView.deselectAll(nil)
  135. }
  136. @IBAction func addBookmarkAction(_ sender: Any) {
  137. delegate?.bkControllerAddAction?(controller: self)
  138. handdler?.addCurrentBookmark()
  139. // let menu = NSMenu()
  140. // let removeItem = NSMenuItem(title: NSLocalizedString("Remove Bookmark", comment: ""), action: #selector(removeBookmark), keyEquivalent: "")
  141. // removeItem.target = self
  142. // menu.addItem(removeItem)
  143. // let removeAllItem = NSMenuItem(title: NSLocalizedString("Remove All Bookmarks", comment: ""), action: #selector(removeAllBookmark), keyEquivalent: "")
  144. // menu.addItem(removeAllItem)
  145. // removeAllItem.target = self
  146. // menu.popUp(positioning: removeItem, at: .init(x: 0, y: 24), in: sender as? NSView)
  147. }
  148. @objc func changeLocationAction() {
  149. if self.bookTableView.selectedRowIndexes.count == 1 {
  150. let item = self.dataSource[self.bookTableView.selectedRowIndexes.first!]
  151. let alter = NSAlert()
  152. alter.alertStyle = NSAlert.Style.informational
  153. alter.messageText = NSLocalizedString("Are you sure you want to set the selected page as the bookmark location?", comment: "")
  154. alter.addButton(withTitle: NSLocalizedString("Yes", comment:""))
  155. alter.addButton(withTitle: NSLocalizedString("No", comment:""))
  156. let modlres = alter.runModal()
  157. if modlres == NSApplication.ModalResponse.alertFirstButtonReturn {
  158. let bookMark = KMBookMarkItem()
  159. bookMark.bookMark = item.bookMark
  160. bookMark.label = item.label
  161. // bookMark.index = UInt(self.listView.currentPageIndex)
  162. self.changeLocation(oldBookMark: item,
  163. newBookMark: bookMark)
  164. }
  165. } else {
  166. __NSBeep()
  167. }
  168. }
  169. @objc func deleteBookAction() {
  170. if self.bookTableView.selectedRowIndexes.count != 0 {
  171. var bookMarks:[KMBookMarkItem] = []
  172. for index in self.bookTableView.selectedRowIndexes {
  173. let item = self.dataSource[index]
  174. bookMarks.append(item)
  175. }
  176. self.deleteBookMark(bookMarks: bookMarks)
  177. } else {
  178. __NSBeep()
  179. }
  180. }
  181. private func renameBookWithRow(row: Int) {
  182. self.renamePDFBook = self.dataSource[row]
  183. self.renameCellView = self.bookTableView.view(atColumn: 0, row: row, makeIfNecessary: true) as! KMBookCellView
  184. self.renameTextField = self.renameCellView.inputTF
  185. // self.renameTextField.delegate = self
  186. self.renameTextField.isEditable = true
  187. self.renameTextField.becomeFirstResponder()
  188. }
  189. @objc func sortAction(_ sender: NSButton) {
  190. let type = self.sortType_
  191. if type == .ascending {
  192. self.sortType_ = .descending
  193. } else {
  194. self.sortType_ = .ascending
  195. }
  196. self.reloadData()
  197. }
  198. //MARK: Noti
  199. @objc func KMPDFViewCurrentPageDidChangedNotification(notification: NSNotification) {
  200. if notification.object is CPDFDocument {
  201. let pdfdocument : CPDFDocument = notification.object as! CPDFDocument
  202. if pdfdocument.isEqual(document) {
  203. if !isLocalEvent {
  204. var containSelIndex:Bool = false
  205. for (index, value) in self.dataSource.enumerated() {
  206. // if value.bookMark == document?.bookmark(forPageIndex: UInt(self.listView.currentPageIndex)) {
  207. containSelIndex = true
  208. self.didSelectItem(row: index, event: NSEvent())
  209. break
  210. // }
  211. }
  212. if !containSelIndex {
  213. self.cancelSelect()
  214. }
  215. }
  216. isLocalEvent = false
  217. }
  218. self.updateAddBookMarkState()
  219. }
  220. }
  221. @objc func documentPageCountChangedNotification(notification: NSNotification) {
  222. if notification.object is CPDFDocument {
  223. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { [weak self] in
  224. let pdfdocument : CPDFDocument = notification.object as! CPDFDocument
  225. if pdfdocument.isEqual(self?.document) {
  226. self?.reloadData()
  227. }
  228. }
  229. }
  230. }
  231. override func interfaceThemeDidChanged(_ appearance: NSAppearance.Name) {
  232. super.interfaceThemeDidChanged(appearance)
  233. let isDark = appearance == .darkAqua
  234. self.view.wantsLayer = true
  235. if isDark {
  236. self.view.layer?.backgroundColor = .clear
  237. self.bookTableView.backgroundColor = .clear
  238. } else {
  239. self.view.layer?.backgroundColor = NSColor(red: 247.0/255.0, green: 248.0/255.0, blue: 250.0/255.0, alpha: 1).cgColor
  240. self.bookTableView.backgroundColor = NSColor.km_init(hex: "#F7F8FA")
  241. }
  242. }
  243. }
  244. // MARK: - NSTextFieldDelegate
  245. extension KMBookMarkViewController: NSTextFieldDelegate {
  246. func controlTextDidEndEditing(_ obj: Notification) {
  247. if (self.renameTextField.isEqual(obj.object)) {
  248. let textField : NSTextField = obj.object as! NSTextField
  249. self.renamePDFBook(bookmark: self.renamePDFBook, label: textField.stringValue)
  250. // self.renameTextField.isEditable = false
  251. }
  252. }
  253. }
  254. // MARK: - NSTableViewDelegate,NSTableViewDataSource
  255. extension KMBookMarkViewController : NSTableViewDelegate,NSTableViewDataSource {
  256. func numberOfRows(in tableView: NSTableView) -> Int {
  257. let count = self.dataSource?.count ?? 0
  258. if count == 0 {
  259. self.emptyView.isHidden = false
  260. } else {
  261. self.emptyView.isHidden = true
  262. }
  263. return count
  264. }
  265. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  266. if row < self.dataSource.count {
  267. let item: KMBookMarkItem = self.dataSource[row]
  268. let cell : KMBookCellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMBookCellView"), owner: self) as! KMBookCellView
  269. cell.inputTF.stringValue = item.bookMark.label
  270. cell.bookTitle.stringValue = "\(item.bookMark.pageIndex + 1)"
  271. cell.inputBox.borderWidth = 0
  272. if let data = item.bookMark.date {
  273. cell.dateLabel.stringValue = KMTools.timeString(timeDate: data)
  274. } else {
  275. cell.dateLabel.stringValue = ""
  276. }
  277. if let page = document?.page(at: UInt(item.bookMark.pageIndex)) {
  278. if let data = page.PDFListViewTIFFData(for: page.bounds) {
  279. let image = NSImage(data: data)
  280. cell.iconIv.image = image
  281. }
  282. }
  283. cell.textFieldDidEndEditingCallback = { [weak self] textF in
  284. self?.renameCellView = cell
  285. self?.renamePDFBook(bookmark: item, label: textF.stringValue)
  286. }
  287. return cell
  288. }
  289. return nil
  290. }
  291. func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
  292. let rowView = KMBookMarkTableRowView()
  293. rowView.selectionHighlightStyle = .none
  294. if row < self.dataSource.count {
  295. rowView.model = self.dataSource[row]
  296. rowView.mouseDownAction = { [unowned self] (view, event) in
  297. self.didSelectItem(row: row, event: event)
  298. }
  299. rowView.rightMouseDownAction = { [unowned self] (view, event) in
  300. if !KMOCToolClass.arrayContains(array: self.selectItems, annotation: rowView.model) ||
  301. self.selectItems.count == 1 {
  302. self.selectIndex(index: row)
  303. }
  304. if row < 0 || row >= self.dataSource.count {
  305. return
  306. }
  307. if self.bookTableView.rowView(atRow: row, makeIfNecessary: false) != nil {
  308. let tempView = self.bookTableView.rowView(atRow: row, makeIfNecessary: false)
  309. self.addMenuTitle(view: tempView!, event: event)
  310. }
  311. }
  312. rowView.hoverCallback = { [unowned self] (mouseEntered, mouseBox) in
  313. self.bookTableView.enumerateAvailableRowViews { view, row in
  314. if view is KMBookMarkTableRowView {
  315. (view as? KMBookMarkTableRowView)?.model.hover = false
  316. (view as? KMBookMarkTableRowView)?.reloadData()
  317. }
  318. }
  319. if mouseEntered {
  320. rowView.model.hover = true
  321. } else {
  322. rowView.model.hover = false
  323. }
  324. }
  325. }
  326. return rowView
  327. }
  328. func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
  329. self.isLocalEvent = true
  330. return true
  331. }
  332. func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
  333. self.isLocalEvent = true
  334. return true
  335. }
  336. func tableViewSelectionDidChange(_ notification: Notification) {
  337. // if self.bookTableView.selectedRow == -1 {
  338. // self.cancelSelect()
  339. // }
  340. }
  341. func selectIndex(index: Int) {
  342. if index < 0 || index >= self.dataSource.count {
  343. return
  344. }
  345. self.bookTableView.selectRowIndexes(IndexSet(integer: IndexSet.Element(index)), byExtendingSelection: false)
  346. self.didSelectItem(row: index, event: NSEvent(), needJump: false)
  347. }
  348. func didSelectItem(row: Int, event: NSEvent?, needJump: Bool = true) {
  349. //当选中一个时
  350. if self.bookTableView.selectedRowIndexes.count == 1 || (event != nil &&
  351. (!event!.modifierFlags.contains(NSEvent.ModifierFlags.command) &&
  352. !event!.modifierFlags.contains(NSEvent.ModifierFlags.shift))) {
  353. self.bookTableView.selectRowIndexes(IndexSet(integer: IndexSet.Element(row)), byExtendingSelection: false)
  354. }
  355. //原始数据置空
  356. for model in self.selectItems {
  357. self.dataSource.contains { KMBookMarkItem in
  358. if KMBookMarkItem.bookMark == model.bookMark {
  359. let index = KMOCToolClass.arrayIndexOf(array: self.dataSource, item: KMBookMarkItem) ?? 0
  360. if index != nil {
  361. KMBookMarkItem.select = false
  362. if self.bookTableView.rowView(atRow: index, makeIfNecessary: false) != nil {
  363. let rowView: KMBookMarkTableRowView = self.bookTableView.rowView(atRow: index, makeIfNecessary: false) as! KMBookMarkTableRowView
  364. rowView.reloadData()
  365. }
  366. }
  367. return true
  368. }
  369. return false
  370. }
  371. }
  372. //获取最新数据
  373. var items: [KMBookMarkItem] = []
  374. for index in self.bookTableView.selectedRowIndexes {
  375. if index < self.dataSource.count {
  376. let model: KMBookMarkItem = self.dataSource[index]
  377. model.select = true
  378. if self.bookTableView.rowView(atRow: index, makeIfNecessary: false) != nil {
  379. let rowView: KMBookMarkTableRowView = self.bookTableView.rowView(atRow: index, makeIfNecessary: false) as! KMBookMarkTableRowView
  380. rowView.reloadData()
  381. }
  382. items.append(model)
  383. }
  384. }
  385. self.selectItems = items
  386. //刷新数据
  387. if needJump {
  388. self.updateListViewData()
  389. }
  390. }
  391. func updateListViewData() {
  392. if self.bookTableView.selectedRowIndexes.count == 1 &&
  393. self.bookTableView.selectedRowIndexes.first! < self.dataSource.count {
  394. let index = self.bookTableView.selectedRowIndexes.first
  395. let selectBookMark = self.dataSource[index!]
  396. // self.listView.go(toPageIndex: selectBookMark.bookMark.pageIndex, animated: true)
  397. }
  398. }
  399. func cancelSelect() {
  400. self.bookTableView.deselectAll(nil)
  401. for model in self.selectItems {
  402. model.select = false
  403. let index = self.dataSource.firstIndex(of: model)
  404. if index != nil {
  405. if (self.bookTableView.rowView(atRow: index!, makeIfNecessary: false) != nil) {
  406. let rowView: KMBookMarkTableRowView = self.bookTableView.rowView(atRow: index!, makeIfNecessary: false) as! KMBookMarkTableRowView
  407. rowView.reloadData()
  408. }
  409. }
  410. }
  411. }
  412. func updateAddBookMarkState() {
  413. // self.addBookButton.isEnabled = self.canAddBorkMark()
  414. }
  415. func canAddBorkMark() -> Bool {
  416. if document?.bookmarks() != nil && document?.bookmarks()?.count != 0 {
  417. for bookMark in document?.bookmarks() ?? [] {
  418. // if bookMark.pageIndex == self.listView.currentPageIndex {
  419. // return false
  420. // }
  421. }
  422. }
  423. return true
  424. }
  425. @objc func removeBookmark(_ sender: NSMenuItem) {
  426. let row = self.bookTableView.selectedRow
  427. if let item = self.dataSource.safe_element(for: row) as? KMBookMarkItem {
  428. // self.listView.document.removeBookmark(forPageIndex: UInt(item.bookMark.pageIndex))
  429. self.deleteBookMark(bookMarks: [item])
  430. }
  431. // DispatchQueue.main.async {
  432. // self.reloadData()
  433. // }
  434. }
  435. @objc func removeAllBookmark(_ sender: NSMenuItem) {
  436. // for data in self.dataSource {
  437. // self.listView.document.removeBookmark(forPageIndex: UInt(data.bookMark.pageIndex))
  438. // }
  439. // DispatchQueue.main.async {
  440. // self.reloadData()
  441. // }
  442. self.deleteBookMark(bookMarks: self.dataSource)
  443. }
  444. }
  445. //MARK: - undoRedo
  446. extension KMBookMarkViewController {
  447. func changeLocation(oldBookMark: KMBookMarkItem, newBookMark: KMBookMarkItem) {
  448. document?.removeBookmark(forPageIndex: oldBookMark.index)
  449. document?.addBookmark(newBookMark.label, forPageIndex: newBookMark.index)
  450. reloadData()
  451. // self.listView.setNeedsDisplayForVisiblePages()
  452. // self.listView.undoManager?.registerUndo(withTarget: self) { [unowned self] targetType in
  453. // self.changeLocation(oldBookMark: newBookMark, newBookMark: oldBookMark)
  454. // }
  455. }
  456. func renamePDFBook(bookmark : KMBookMarkItem! , label:String) {
  457. if bookmark.bookMark.label == label {
  458. return
  459. }
  460. let temp = bookmark.bookMark.label
  461. bookmark.bookMark.label = label
  462. self.reloadData()
  463. var indexSet = IndexSet()
  464. indexSet.insert(self.bookTableView.row(for: self.renameCellView))
  465. self.bookTableView.selectRowIndexes(indexSet, byExtendingSelection: false)
  466. // self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
  467. // bookmark.bookMark.label = label
  468. // self?.renamePDFBook(bookmark: bookmark, label: temp ?? bookmark.label)
  469. // }
  470. }
  471. func deleteBookMark(bookMarks: [KMBookMarkItem]) {
  472. for bookMark in bookMarks {
  473. if ((document?.removeBookmark(forPageIndex: bookMark.index)) != nil) {
  474. KMPrint("删除标签成功")
  475. }
  476. }
  477. // self.listView.setNeedsDisplayForVisiblePages()
  478. self.reloadData()
  479. //undo redo
  480. var saveBooks:[KMBookMarkItem] = bookMarks
  481. // self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
  482. // saveBooks.sort(){$0.index > $1.index}
  483. // self?.addBookMark(bookMarks: bookMarks)
  484. // }
  485. guard let callBack = bookMarkDidChange else { return }
  486. callBack(self, bookMarks)
  487. }
  488. func addBookMark(bookMarks: [KMBookMarkItem]) {
  489. for bookMark in bookMarks {
  490. document?.addBookmark(bookMark.label, forPageIndex: UInt(bookMark.index))
  491. }
  492. // self.listView.setNeedsDisplayForVisiblePages()
  493. self.reloadData()
  494. if bookMarks.count == 1 {
  495. DispatchQueue.main.async { [self] in
  496. if document?.bookmark(forPageIndex: UInt(bookMarks.first!.index)) != nil {
  497. let item = KMBookMarkItem()
  498. item.bookMark = (document?.bookmark(forPageIndex: UInt(bookMarks.first!.index)))!
  499. item.label = item.bookMark.label
  500. item.index = UInt(item.bookMark.pageIndex)
  501. self.addBookMarkAndEdit(newBookMark: item)
  502. }
  503. }
  504. }
  505. //undo redo
  506. var saveBooks:[KMBookMarkItem] = bookMarks
  507. // self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
  508. // saveBooks.sort(){$0.index > $1.index}
  509. // self?.deleteBookMark(bookMarks: saveBooks)
  510. // }
  511. guard let callBack = bookMarkDidChange else { return }
  512. callBack(self, bookMarks)
  513. }
  514. @IBAction func undo(_ sender: Any) {
  515. // if (self.listView.undoManager?.canUndo ?? false) {
  516. // self.listView.undoManager?.undo()
  517. // }
  518. }
  519. @IBAction func redo(_ sender: Any) {
  520. // if (self.listView.undoManager?.canRedo ?? false) {
  521. // self.listView.undoManager?.redo()
  522. // }
  523. }
  524. }
  525. // MARK: - NSMenuDelegate, NSMenuItemValidation
  526. extension KMBookMarkViewController: NSMenuDelegate, NSMenuItemValidation {
  527. func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
  528. let action = menuItem.action
  529. if (action == #selector(undo)) {
  530. // return self.listView.undoManager?.canUndo ?? false
  531. }
  532. if (action == #selector(redo)) {
  533. // return self.listView.undoManager?.canRedo ?? false
  534. }
  535. if action == #selector(renameBookAction) ||
  536. action == #selector(changeLocationAction) ||
  537. action == #selector(deleteBookAction) {
  538. if self.bookTableView.selectedRowIndexes.count > 1 {
  539. if action == #selector(changeLocationAction) {
  540. return false
  541. } else if action == #selector(renameBookAction) {
  542. return false
  543. }
  544. } else if self.bookTableView.selectedRowIndexes.count == 1 {
  545. return true
  546. } else {
  547. if self.bookTableView.selectedRowIndexes.count == 0 {
  548. if action == #selector(changeLocationAction) {
  549. // if self.listView.document.bookmark(forPageIndex: UInt(self.listView.currentPageIndex)) != nil {
  550. // return false
  551. // }
  552. }
  553. } else {
  554. return false
  555. }
  556. }
  557. }
  558. if action == #selector(removeBookmark) {
  559. let row = self.bookTableView.selectedRow
  560. return row >= 0 && row < self.dataSource.count
  561. }
  562. if action == #selector(removeAllBookmark) {
  563. return self.dataSource.count > 0
  564. }
  565. return true
  566. }
  567. }
  568. class KMBookMarkItem: NSObject {
  569. var label: String = ""
  570. var index: UInt = 0
  571. var bookMark: CPDFBookmark = CPDFBookmark()
  572. var select: Bool = false
  573. var hover: Bool = false
  574. }