KMBookMarkViewController.swift 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. //
  2. // KMBookMarkViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lxy on 2022/10/10.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. typealias KMBookMarkViewControllerBookMarkDidChange = (_ controller: KMBookMarkViewController, _ bookMarks: [KMBookMarkItem]) -> Void
  10. @objc protocol KMBookMarkViewControllerDelegate: NSObjectProtocol {
  11. @objc optional func bkControllerAddAction(controller: KMBookMarkViewController, bookmark: CPDFBookmark?, info: [String : Any]?)
  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: KMBotaTableView!
  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. weak var document: CPDFDocument?
  27. var isLocalEvent: Bool = false //区分外部点击还是内部点击
  28. var selectItems: [KMBookMarkItem] = []
  29. var bookMarkDidChange: KMBookMarkViewControllerBookMarkDidChange?
  30. weak var delegate: KMBookMarkViewControllerDelegate?
  31. private lazy var handdler_ = KMNBookmarkHanddler()
  32. // 升序
  33. private var sortType_: KMSortMode = .ascending
  34. private lazy var addButton_: ComponentButton = {
  35. let view = ComponentButton()
  36. view.properties = ComponentButtonProperty(type: .text_gray, size: .xxs, onlyIcon: true, icon: NSImage(named: "KMBookmarkAdd"))
  37. return view
  38. }()
  39. private var emptyView_: ComponentEmpty = {
  40. let view = ComponentEmpty()
  41. view.properties = ComponentEmptyProperty(emptyType: .noBookmark, state: .normal, image: NSImage(named: "KMBookmarkEmpty"), text: KMLocalizedString("No Bookmark"), subText: KMLocalizedString("Here is the description."))
  42. return view
  43. }()
  44. var handdler: KMNBookmarkHanddler {
  45. get {
  46. return handdler_
  47. }
  48. }
  49. private var groupView: ComponentGroup? = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
  50. convenience init() {
  51. self.init(nibName: "KMBookMarkViewController", bundle: nil)
  52. }
  53. override func viewDidLoad() {
  54. super.viewDidLoad()
  55. handdler.delegate = self
  56. titleTextField.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-bold")
  57. addBookButton.addSubview(addButton_)
  58. addButton_.frame = addBookButton.bounds
  59. addButton_.autoresizingMask = [.width, .height]
  60. addButton_.setTarget(self, action: #selector(addBookmarkAction))
  61. bookTableView.style = NSTableView.Style.plain
  62. bookTableView.allowsMultipleSelection = true
  63. bookTableView.doubleAction = #selector(renameBookAction)
  64. bookTableView.hasImageToolTips = true
  65. bookTableView.botaDelegate = self
  66. sortButton.image = NSImage(named: "KMImageNameBotaBookmarkSortIcon")
  67. sortButton.target = self
  68. sortButton.action = #selector(sortAction)
  69. emptyView.addSubview(emptyView_)
  70. emptyView_.km_add_top_constraint(constant: 232)
  71. emptyView_.km_add_bottom_constraint()
  72. emptyView_.km_add_leading_constraint()
  73. emptyView_.km_add_trailing_constraint()
  74. self.reloadData()
  75. }
  76. override func updateUILanguage() {
  77. super.updateUILanguage()
  78. KMMainThreadExecute {
  79. self.titleTextField.stringValue = KMLocalizedString("Bookmarks")
  80. }
  81. }
  82. override func updateUIThemeColor() {
  83. super.updateUIThemeColor()
  84. KMMainThreadExecute {
  85. self.view.wantsLayer = true
  86. let color = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle")
  87. self.view.layer?.backgroundColor = color.cgColor
  88. self.topSeplineView.wantsLayer = true
  89. self.topSeplineView.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/divider").cgColor
  90. self.titleTextField.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
  91. }
  92. }
  93. func reloadData() {
  94. let array = document?.bookmarks() ?? [CPDFBookmark]()
  95. var bookMarks: [KMBookMarkItem] = []
  96. for bookMark in array {
  97. let item = KMBookMarkItem()
  98. item.bookMark = bookMark
  99. item.index = UInt(bookMark.pageIndex)
  100. item.label = bookMark.label
  101. bookMarks.append(item)
  102. }
  103. self.dataSource = bookMarks
  104. if self.sortType_ == .descending {
  105. self.dataSource.sort(){$0.bookMark.pageIndex >= $1.bookMark.pageIndex}
  106. } else {
  107. self.dataSource.sort(){$0.bookMark.pageIndex < $1.bookMark.pageIndex}
  108. }
  109. self.bookTableView.reloadData()
  110. self.updateAddBookMarkState()
  111. }
  112. func addBookMarkAndEdit(newBookMark: KMBookMarkItem) {
  113. _ = self.dataSource.contains { KMBookMarkItem in
  114. if KMBookMarkItem.bookMark == newBookMark.bookMark {
  115. let index = KMOCToolClass.arrayIndexOf(array: self.dataSource, item: KMBookMarkItem) ?? 0
  116. self.didSelectItem(row: index, event: NSEvent())
  117. self.renameBookWithRow(row: index)
  118. return true
  119. }
  120. return false
  121. }
  122. }
  123. override func addNotifations() {
  124. super.addNotifations()
  125. NotificationCenter.default.addObserver(self, selector: #selector(KMPDFViewCurrentPageDidChangedNotification), name: NSNotification.Name.init(rawValue: "KMPDFViewCurrentPageDidChanged"), object: nil)
  126. NotificationCenter.default.addObserver(self, selector: #selector(documentPageCountChangedNotification), name: NSNotification.Name.init(rawValue: "CPDFDocumentPageCountChangedNotification"), object: nil)
  127. }
  128. //MARK: - Menu Action
  129. @objc func renameBookAction() {
  130. if self.bookTableView.selectedRowIndexes.count == 1 {
  131. self.renameBookWithRow(row: self.bookTableView.selectedRowIndexes.first!)
  132. } else {
  133. __NSBeep()
  134. }
  135. }
  136. @IBAction func escButtonAction(_ sender: Any) {
  137. self.bookTableView.deselectAll(nil)
  138. }
  139. @IBAction func addBookmarkAction(_ sender: Any) {
  140. let currentPageIndex = handdler.currentPageIndex
  141. if let data = handdler.bookmark(for: currentPageIndex) {
  142. delegate?.bkControllerAddAction?(controller: self, bookmark: data, info: ["result" : false])
  143. return
  144. }
  145. handdler.addCurrentBookmark(callback: { [unowned self] bookmark in
  146. self.delegate?.bkControllerAddAction?(controller: self, bookmark: bookmark, info: nil)
  147. self.reloadData()
  148. })
  149. }
  150. @objc func changeLocationAction() {
  151. if self.bookTableView.selectedRowIndexes.count == 1 {
  152. let item = self.dataSource[self.bookTableView.selectedRowIndexes.first!]
  153. let alter = NSAlert()
  154. alter.alertStyle = NSAlert.Style.informational
  155. alter.messageText = KMLocalizedString("Are you sure you want to set the selected page as the bookmark location?", comment: "")
  156. alter.addButton(withTitle: KMLocalizedString("Yes", comment:""))
  157. alter.addButton(withTitle: KMLocalizedString("No", comment:""))
  158. let modlres = alter.runModal()
  159. if modlres == NSApplication.ModalResponse.alertFirstButtonReturn {
  160. let bookMark = KMBookMarkItem()
  161. bookMark.bookMark = item.bookMark
  162. bookMark.label = item.label
  163. bookMark.index = UInt(handdler.currentPageIndex)
  164. self.changeLocation(oldBookMark: item,
  165. newBookMark: bookMark)
  166. }
  167. } else {
  168. __NSBeep()
  169. }
  170. }
  171. @objc func deleteBookAction() {
  172. if self.bookTableView.selectedRowIndexes.count != 0 {
  173. var bookMarks:[KMBookMarkItem] = []
  174. for index in self.bookTableView.selectedRowIndexes {
  175. let item = self.dataSource[index]
  176. bookMarks.append(item)
  177. }
  178. self.deleteBookMark(bookMarks: bookMarks)
  179. } else {
  180. __NSBeep()
  181. }
  182. }
  183. private func renameBookWithRow(row: Int) {
  184. self.renamePDFBook = self.dataSource[row]
  185. self.renameCellView = self.bookTableView.view(atColumn: 0, row: row, makeIfNecessary: true) as? KMBookCellView
  186. self.renameTextField = self.renameCellView?.inputTF
  187. self.renameTextField?.delegate = self
  188. self.renameTextField?.isEditable = true
  189. self.renameTextField?.becomeFirstResponder()
  190. }
  191. @objc func sortAction(_ sender: NSButton) {
  192. let type = self.sortType_
  193. if type == .ascending {
  194. self.sortType_ = .descending
  195. } else {
  196. self.sortType_ = .ascending
  197. }
  198. self.reloadData()
  199. }
  200. //MARK: - Noti
  201. @objc func KMPDFViewCurrentPageDidChangedNotification(notification: NSNotification) {
  202. if notification.object is CPDFDocument {
  203. let pdfdocument : CPDFDocument = notification.object as! CPDFDocument
  204. if pdfdocument.isEqual(document) {
  205. if !isLocalEvent {
  206. var containSelIndex:Bool = false
  207. for (index, value) in self.dataSource.enumerated() {
  208. if value.bookMark == document?.bookmark(forPageIndex: UInt(handdler.currentPageIndex)) {
  209. containSelIndex = true
  210. self.didSelectItem(row: index, event: NSEvent())
  211. break
  212. }
  213. }
  214. if !containSelIndex {
  215. self.cancelSelect()
  216. }
  217. }
  218. isLocalEvent = false
  219. }
  220. self.updateAddBookMarkState()
  221. }
  222. }
  223. @objc func documentPageCountChangedNotification(notification: NSNotification) {
  224. if notification.object is CPDFDocument {
  225. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { [weak self] in
  226. let pdfdocument : CPDFDocument = notification.object as! CPDFDocument
  227. if pdfdocument.isEqual(self?.document) {
  228. self?.reloadData()
  229. }
  230. }
  231. }
  232. }
  233. }
  234. // MARK: - NSTextFieldDelegate
  235. extension KMBookMarkViewController: NSTextFieldDelegate {
  236. func controlTextDidEndEditing(_ obj: Notification) {
  237. if (self.renameTextField!.isEqual(obj.object)) {
  238. let textField : NSTextField = obj.object as! NSTextField
  239. handdler.rename(bookmark: renamePDFBook!.bookMark, label: textField.stringValue)
  240. self.renameTextField?.isEditable = false
  241. }
  242. }
  243. }
  244. // MARK: - NSTableViewDelegate,NSTableViewDataSource
  245. extension KMBookMarkViewController : NSTableViewDelegate,NSTableViewDataSource {
  246. func numberOfRows(in tableView: NSTableView) -> Int {
  247. let count = self.dataSource.count
  248. if count == 0 {
  249. self.emptyView.isHidden = false
  250. } else {
  251. self.emptyView.isHidden = true
  252. }
  253. return count
  254. }
  255. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  256. if row < self.dataSource.count {
  257. let item: KMBookMarkItem = self.dataSource[row]
  258. let cell : KMBookCellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMBookCellView"), owner: self) as! KMBookCellView
  259. cell.inputTF.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-regular")
  260. cell.inputTF.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/1")
  261. cell.inputTF.stringValue = item.bookMark.label
  262. cell.bookTitle.stringValue = "\(item.bookMark.pageIndex + 1)"
  263. cell.inputBox.borderWidth = 0
  264. if let data = item.bookMark.date {
  265. cell.dateLabel.stringValue = KMTools.timeString(timeDate: data)
  266. } else {
  267. cell.dateLabel.stringValue = ""
  268. }
  269. cell.textFieldDidEndEditingCallback = { [weak self] textF in
  270. self?.renameCellView = cell
  271. self?.handdler.rename(bookmark: item.bookMark, label: textF.stringValue)
  272. }
  273. return cell
  274. }
  275. return nil
  276. }
  277. func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
  278. let rowView = KMBookMarkTableRowView()
  279. rowView.selectionHighlightStyle = .none
  280. if row < self.dataSource.count {
  281. rowView.model = self.dataSource[row]
  282. rowView.menuClickedAction = { [weak self] point in
  283. let idxs = self?.bookTableView.selectedRowIndexes.count ?? 0
  284. let tempView = self?.bookTableView.rowView(atRow: row, makeIfNecessary: false)
  285. var viewHeight: CGFloat = 0
  286. let items: [String] = ["Delete", "Add", "Rename", "Delete All"]
  287. var menuItemArr: [ComponentMenuitemProperty] = []
  288. for value in items {
  289. let properties_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  290. itemSelected: false,
  291. isDisabled: false,
  292. keyEquivalent: nil,
  293. text: KMLocalizedString(value),
  294. identifier: value)
  295. menuItemArr.append(properties_Menuitem)
  296. viewHeight += 36
  297. }
  298. if idxs > 1 {
  299. (menuItemArr.safe_element(for: 1) as? ComponentMenuitemProperty)?.isDisabled = true
  300. (menuItemArr.safe_element(for: 2) as? ComponentMenuitemProperty)?.isDisabled = true
  301. }
  302. if self?.groupView != nil {
  303. self?.groupView?.clickedAutoHide = false
  304. self?.groupView?.groupDelegate = self
  305. self?.groupView?.frame = CGRectMake(0, 0, 180, viewHeight)
  306. self?.groupView?.updateGroupInfo(menuItemArr)
  307. self?.groupView?.showWithPoint(CGPoint(x: point.x, y: point.y - viewHeight), relativeTo: tempView)
  308. }
  309. return NSMenu()
  310. }
  311. rowView.mouseDownAction = { [unowned self] (view, event) in
  312. self.didSelectItem(row: row, event: event)
  313. }
  314. rowView.rightMouseDownAction = { [unowned self] (view, event) in
  315. if !KMOCToolClass.arrayContains(array: self.selectItems, annotation: rowView.model) ||
  316. self.selectItems.count == 1 {
  317. self.selectIndex(index: row)
  318. }
  319. if row < 0 || row >= self.dataSource.count {
  320. return
  321. }
  322. }
  323. rowView.hoverCallback = { [unowned self] (mouseEntered, mouseBox) in
  324. if let value = ComponentLibrary.shared.getComponentValueFromKey("radius/xs") {
  325. let currentValue = value as? CGFloat ?? 0
  326. rowView.box?.cornerRadius = currentValue
  327. }
  328. self.bookTableView.enumerateAvailableRowViews { view, row in
  329. if let data = view as? KMBookMarkTableRowView {
  330. data.model.hover = false
  331. data.reloadData()
  332. }
  333. }
  334. if mouseEntered {
  335. rowView.model.hover = true
  336. rowView.reloadData()
  337. } else {
  338. rowView.model.hover = false
  339. rowView.reloadData()
  340. }
  341. }
  342. }
  343. return rowView
  344. }
  345. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  346. return 36
  347. }
  348. func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
  349. self.isLocalEvent = true
  350. return true
  351. }
  352. func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
  353. self.isLocalEvent = true
  354. return true
  355. }
  356. func tableViewSelectionDidChange(_ notification: Notification) {
  357. // if self.bookTableView.selectedRow == -1 {
  358. // self.cancelSelect()
  359. // }
  360. }
  361. func selectIndex(index: Int) {
  362. if index < 0 || index >= self.dataSource.count {
  363. return
  364. }
  365. self.bookTableView.selectRowIndexes(IndexSet(integer: IndexSet.Element(index)), byExtendingSelection: false)
  366. self.didSelectItem(row: index, event: NSEvent(), needJump: false)
  367. }
  368. func didSelectItem(row: Int, event: NSEvent?, needJump: Bool = true) {
  369. //当选中一个时
  370. if self.bookTableView.selectedRowIndexes.count == 1 || (event != nil &&
  371. (!event!.modifierFlags.contains(NSEvent.ModifierFlags.command) &&
  372. !event!.modifierFlags.contains(NSEvent.ModifierFlags.shift))) {
  373. self.bookTableView.selectRowIndexes(IndexSet(integer: IndexSet.Element(row)), byExtendingSelection: false)
  374. }
  375. //原始数据置空
  376. for model in self.selectItems {
  377. self.dataSource.contains { KMBookMarkItem in
  378. if KMBookMarkItem.bookMark == model.bookMark {
  379. let index = KMOCToolClass.arrayIndexOf(array: self.dataSource, item: KMBookMarkItem) ?? 0
  380. if index != nil {
  381. KMBookMarkItem.select = false
  382. if self.bookTableView.rowView(atRow: index, makeIfNecessary: false) != nil {
  383. let rowView: KMBookMarkTableRowView = self.bookTableView.rowView(atRow: index, makeIfNecessary: false) as! KMBookMarkTableRowView
  384. rowView.reloadData()
  385. }
  386. }
  387. return true
  388. }
  389. return false
  390. }
  391. }
  392. //获取最新数据
  393. var items: [KMBookMarkItem] = []
  394. for index in self.bookTableView.selectedRowIndexes {
  395. if index < self.dataSource.count {
  396. let model: KMBookMarkItem = self.dataSource[index]
  397. model.select = true
  398. if self.bookTableView.rowView(atRow: index, makeIfNecessary: false) != nil {
  399. let rowView: KMBookMarkTableRowView = self.bookTableView.rowView(atRow: index, makeIfNecessary: false) as! KMBookMarkTableRowView
  400. rowView.reloadData()
  401. }
  402. items.append(model)
  403. }
  404. }
  405. self.selectItems = items
  406. //刷新数据
  407. if needJump {
  408. self.updateListViewData()
  409. }
  410. }
  411. func updateListViewData() {
  412. if self.bookTableView.selectedRowIndexes.count == 1 &&
  413. self.bookTableView.selectedRowIndexes.first! < self.dataSource.count {
  414. let index = self.bookTableView.selectedRowIndexes.first
  415. let selectBookMark = self.dataSource[index!]
  416. // self.listView.go(toPageIndex: selectBookMark.bookMark.pageIndex, animated: true)
  417. }
  418. }
  419. func cancelSelect() {
  420. self.bookTableView.deselectAll(nil)
  421. for model in self.selectItems {
  422. model.select = false
  423. let index = self.dataSource.firstIndex(of: model)
  424. if index != nil {
  425. if (self.bookTableView.rowView(atRow: index!, makeIfNecessary: false) != nil) {
  426. let rowView: KMBookMarkTableRowView = self.bookTableView.rowView(atRow: index!, makeIfNecessary: false) as! KMBookMarkTableRowView
  427. rowView.reloadData()
  428. }
  429. }
  430. }
  431. }
  432. func updateAddBookMarkState() {
  433. addButton_.properties.isDisabled = !canAddBorkMark()
  434. addButton_.reloadData()
  435. }
  436. func canAddBorkMark() -> Bool {
  437. if document?.bookmarks() != nil && document?.bookmarks()?.count != 0 {
  438. for bookMark in document?.bookmarks() ?? [] {
  439. if bookMark.pageIndex == handdler.currentPageIndex {
  440. return false
  441. }
  442. }
  443. }
  444. return true
  445. }
  446. }
  447. // MARK: - KMBotaTableViewDelegate
  448. extension KMBookMarkViewController: KMBotaTableViewDelegate {
  449. func tableView(_ aTableView: NSTableView, imageContextForRow rowIndex: Int) -> AnyObject? {
  450. if aTableView.isEqual(to: self.bookTableView) {
  451. let cnt = self.dataSource.count
  452. if rowIndex >= cnt {
  453. return nil
  454. }
  455. let model = self.dataSource[rowIndex]
  456. return model.bookMark
  457. }
  458. return nil
  459. }
  460. }
  461. //MARK: - undoRedo
  462. extension KMBookMarkViewController {
  463. func changeLocation(oldBookMark: KMBookMarkItem, newBookMark: KMBookMarkItem) {
  464. document?.removeBookmark(forPageIndex: oldBookMark.index)
  465. document?.addBookmark(newBookMark.label, forPageIndex: newBookMark.index)
  466. reloadData()
  467. }
  468. func renamePDFBook(bookmark : KMBookMarkItem! , label:String) {
  469. if bookmark.bookMark.label == label {
  470. return
  471. }
  472. let temp = bookmark.bookMark.label
  473. bookmark.bookMark.label = label
  474. self.reloadData()
  475. var indexSet = IndexSet()
  476. indexSet.insert(self.bookTableView.row(for: self.renameCellView!))
  477. self.bookTableView.selectRowIndexes(indexSet, byExtendingSelection: false)
  478. }
  479. func deleteBookMark(bookMarks: [KMBookMarkItem]) {
  480. for bookMark in bookMarks {
  481. if ((document?.removeBookmark(forPageIndex: bookMark.index)) != nil) {
  482. KMPrint("删除标签成功")
  483. }
  484. }
  485. self.reloadData()
  486. guard let callBack = bookMarkDidChange else { return }
  487. callBack(self, bookMarks)
  488. }
  489. func addBookMark(bookMarks: [KMBookMarkItem]) {
  490. for bookMark in bookMarks {
  491. document?.addBookmark(bookMark.label, forPageIndex: UInt(bookMark.index))
  492. }
  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. guard let callBack = bookMarkDidChange else { return }
  506. callBack(self, bookMarks)
  507. }
  508. @IBAction func undo(_ sender: Any) {
  509. handdler.undo()
  510. }
  511. @IBAction func redo(_ sender: Any) {
  512. handdler.redo()
  513. }
  514. }
  515. // MARK: - NSMenuDelegate, NSMenuItemValidation
  516. extension KMBookMarkViewController: NSMenuDelegate, NSMenuItemValidation {
  517. func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
  518. let action = menuItem.action
  519. if (action == #selector(undo)) {
  520. return handdler.canUndo()
  521. }
  522. if (action == #selector(redo)) {
  523. return handdler.canRedo()
  524. }
  525. if action == #selector(renameBookAction) ||
  526. action == #selector(changeLocationAction) ||
  527. action == #selector(deleteBookAction) {
  528. if self.bookTableView.selectedRowIndexes.count > 1 {
  529. if action == #selector(changeLocationAction) {
  530. return false
  531. } else if action == #selector(renameBookAction) {
  532. return false
  533. }
  534. } else if self.bookTableView.selectedRowIndexes.count == 1 {
  535. return true
  536. } else {
  537. if self.bookTableView.selectedRowIndexes.count == 0 {
  538. if action == #selector(changeLocationAction) {}
  539. } else {
  540. return false
  541. }
  542. }
  543. }
  544. return true
  545. }
  546. }
  547. extension KMBookMarkViewController: KMNBookmarkHanddlerDelegate {
  548. func handdler(_ handdler: KMNBookmarkHanddler, didAdd bookmark: CPDFBookmark?, info: [String : Any]?) {
  549. KMMainThreadExecute {
  550. self.reloadData()
  551. }
  552. }
  553. func handdler(_ handdler: KMNBookmarkHanddler, didRemove bookmark: CPDFBookmark?, info: [String : Any]?) {
  554. KMMainThreadExecute {
  555. self.reloadData()
  556. }
  557. }
  558. func handdler(_ handdler: KMNBookmarkHanddler, didRemoveAll info: [String : Any]?) {
  559. KMMainThreadExecute {
  560. self.reloadData()
  561. }
  562. }
  563. func handdler(_ handdler: KMNBookmarkHanddler, didRename bookmark: CPDFBookmark?, info: [String : Any]?) {
  564. KMMainThreadExecute {
  565. self.reloadData()
  566. }
  567. }
  568. }
  569. extension KMBookMarkViewController: ComponentGroupDelegate {
  570. func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) {
  571. if let selItem = menuItemProperty {
  572. let index = group?.menuItemArr.firstIndex(of: selItem)
  573. if index == 0 {
  574. group?.removeFromSuperview()
  575. var pageIndexs = IndexSet()
  576. for i in bookTableView.selectedRowIndexes {
  577. if let item = dataSource.safe_element(for: i) as? KMBookMarkItem {
  578. pageIndexs.insert(item.bookMark.pageIndex)
  579. }
  580. }
  581. _ = handdler.removeBookmarks(for: pageIndexs)
  582. } else if index == 1 {
  583. } else if index == 2 {
  584. group?.removeFromSuperview()
  585. renameBookAction()
  586. } else if index == 3 {
  587. Task {
  588. let resp = await KMAlertTool.runModel(message: KMLocalizedString("此操作将删除文档中的所有书签,是否继续?"), buttons: [KMLocalizedString("OK"), KMLocalizedString("No")])
  589. if resp == .alertFirstButtonReturn {
  590. _ = handdler.removeAllBookmarks()
  591. }
  592. }
  593. }
  594. }
  595. }
  596. func componentGroupDidDismiss(group: ComponentGroup?) {
  597. self.groupView?.removeFromSuperview()
  598. }
  599. }
  600. class KMBookMarkItem: NSObject {
  601. var label: String = ""
  602. var index: UInt = 0
  603. var bookMark: CPDFBookmark = CPDFBookmark()
  604. var select: Bool = false
  605. var hover: Bool = false
  606. }