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