KMLeftSideViewController+Outline.swift 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. //
  2. // KMLeftSideViewController+Outline.swift
  3. // PDF Master
  4. //
  5. // Created by tangchao on 2023/12/22.
  6. //
  7. import Foundation
  8. enum KMOutlineViewMenuItemTag: Int {
  9. case addEntry = 0
  10. case addChild
  11. case addAunt
  12. case remove
  13. case edit
  14. case setDestination
  15. case rename
  16. case promote
  17. case demote
  18. }
  19. extension KMLeftSideViewController {
  20. func updateOutlineSelection() {
  21. // if ([[pdfView document] outlineRoot] == nil || mwcFlags.updatingOutlineSelection)
  22. if self.listView.document.outlineRoot() == nil {
  23. return
  24. }
  25. // mwcFlags.updatingOutlineSelection = YES;
  26. let numRows = self.tocOutlineView.numberOfRows
  27. var arr = NSMutableArray()
  28. for i in 0 ..< numRows {
  29. guard let tPDFOutline = self.tocOutlineView.item(atRow: i) as? CPDFOutline else {
  30. continue
  31. }
  32. let tPage = tPDFOutline.destination.page()
  33. if (tPage == nil) {
  34. continue
  35. }
  36. let tDict = NSDictionary(object: tPage as Any, forKey: "\(i)" as NSCopying)
  37. arr.add(tDict)
  38. }
  39. let currentPage = self.listView.currentPage()
  40. var hasExistInOutlineView = false
  41. for dict in arr {
  42. guard let _dict = dict as? NSDictionary else {
  43. continue
  44. }
  45. let page = _dict.allValues.last as? CPDFPage
  46. // NSInteger index = [dict.allKeys.lastObject integerValue];
  47. let index = Int(_dict.allKeys.last as? String ?? "0") ?? 0
  48. if let data = page?.isEqual(to: currentPage), data {
  49. self.tocOutlineView.selectRowIndexes(IndexSet(integer: index), byExtendingSelection: false)
  50. self.tocOutlineView.scrollRowToVisible(index)
  51. hasExistInOutlineView = true
  52. break
  53. }
  54. }
  55. if (!hasExistInOutlineView) {
  56. self.tocOutlineView.deselectRow(self.tocOutlineView.selectedRow)
  57. }
  58. // mwcFlags.updatingOutlineSelection = NO;
  59. }
  60. func newAddOutlineEntryEditingMode(_ index: Int) {
  61. self.renamePDFOutline = self.tocOutlineView.item(atRow: self.tocOutlineView.selectedRow) as? CPDFOutline
  62. let row = self.tocOutlineView.selectedRow
  63. let viewS = self.tocOutlineView.view(atColumn: 0, row: row, makeIfNecessary: true)
  64. let targrtTextField = viewS?.subviews.first as? NSTextField
  65. self.renamePDFOutlineTextField = targrtTextField
  66. targrtTextField?.delegate = self
  67. targrtTextField?.isEditable = true
  68. targrtTextField?.becomeFirstResponder()
  69. }
  70. func loadUnfoldDate(_ foldType: KMFoldType) {
  71. self.allFoldNotes.removeAll()
  72. var mutableArray: [CPDFAnnotation] = []
  73. for note in self.notes {
  74. if note is CPDFMarkupAnnotation {
  75. mutableArray.append(note)
  76. }
  77. }
  78. self.canFoldNotes = mutableArray
  79. self.allFoldNotes = []
  80. }
  81. func selectedRowIndexes() -> IndexSet {
  82. var selectedIndexes = self.tocOutlineView.selectedRowIndexes
  83. let clickedRow = self.tocOutlineView.clickedRow
  84. if clickedRow != -1 && selectedIndexes.contains(clickedRow) == false {
  85. var indexes = IndexSet(integer: clickedRow)
  86. selectedIndexes = indexes
  87. }
  88. return selectedIndexes
  89. }
  90. func addoutline(parent parentOutline: CPDFOutline?, addOutline: CPDFOutline, index: Int, needExpand: Bool) {
  91. var tempO = addOutline
  92. if addOutline.label != nil {
  93. parentOutline?.insertChild(addOutline, at: UInt(index))
  94. } else {
  95. let outline = parentOutline?.insertChild(at: UInt(index))
  96. outline?.label = String(format: "%@ %ld", KMLocalizedString("Page", nil), self.listView.currentPageIndex+1)
  97. outline?.destination = self.listView.currentDestination
  98. tempO = outline!
  99. }
  100. // [[[self.document undoManager] prepareWithInvocationTarget:self] removeOutlineWithParent:parentOutline removeOutline:addOutline index:index needExpand:needExpand];
  101. self.view.window?.makeFirstResponder(nil)
  102. Task { @MainActor in
  103. self.tocOutlineView.reloadData()
  104. if (needExpand) {
  105. self.tocOutlineView.expandItem(parentOutline)
  106. }
  107. let idx = self.tocOutlineView.row(forItem: tempO)
  108. self.tocOutlineView.selectRowIndexes(IndexSet(integer: idx), byExtendingSelection: false)
  109. self.newAddOutlineEntryEditingMode(index)
  110. }
  111. // __block PDFOutline *taddOutline = [addOutline retain];
  112. // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  113. // [self.leftSideController.tocOutlineView scrollRowToVisible:[leftSideController.tocOutlineView rowForItem:taddOutline]];
  114. // [taddOutline release];
  115. // });
  116. }
  117. func removeOutline(parent parentOutline: CPDFOutline?, removeOutline: CPDFOutline, index: Int, needExpand: Bool) {
  118. // [[[self.document undoManager] prepareWithInvocationTarget:self] addoutlineWithParent:parentOutline addOutline:removeOutline index:index needExpand:YES];
  119. removeOutline.removeFromParent()
  120. if (needExpand) {
  121. self.tocOutlineView.expandItem(parentOutline)
  122. }
  123. Task { @MainActor in
  124. self.tocOutlineView.reloadData()
  125. }
  126. }
  127. @objc dynamic func changePDFOutlineDestination(_ destination: CPDFDestination, PDFoutline outline: CPDFOutline) {
  128. (self.listView.undoManager?.prepare(withInvocationTarget: self) as AnyObject).changePDFOutlineDestination(outline.destination, PDFoutline: outline)
  129. outline.destination = destination
  130. }
  131. }
  132. // MARK: - Menu Actions
  133. extension KMLeftSideViewController {
  134. //添加子节点
  135. @objc func outlineContextMenuItemClicked_AddChildEntry(_ sender: AnyObject?) {
  136. let PDFOutlineArray = NSMutableArray()
  137. let rowSet = self.selectedRowIndexes()
  138. for idx in rowSet {
  139. PDFOutlineArray.add(self.tocOutlineView.item(atRow: idx))
  140. }
  141. let currentPDFline = PDFOutlineArray.lastObject as? CPDFOutline
  142. let addOutLine = CPDFOutline()
  143. addOutLine.label = String(format: "%@ %ld", KMLocalizedString("Page", nil), "\(self.listView.currentPageIndex + 1)")
  144. addOutLine.destination = self.listView.currentDestination
  145. self.addoutline(parent: currentPDFline, addOutline: addOutLine, index: Int(currentPDFline?.numberOfChildren ?? 0), needExpand: true)
  146. }
  147. //添加上一级节点
  148. @objc func outlineContextMenuItemClicked_AddAuntEntry(_ sender: AnyObject?) {
  149. let PDFOutlineArray = NSMutableArray()
  150. let rowSet = self.selectedRowIndexes()
  151. for idx in rowSet {
  152. PDFOutlineArray.add(self.tocOutlineView.item(atRow: idx))
  153. }
  154. let clickedOutline = PDFOutlineArray.lastObject as? CPDFOutline
  155. let fatherOutLine = clickedOutline?.parent
  156. let grandfatherOutLine = fatherOutLine?.parent
  157. if (grandfatherOutLine != nil) {
  158. let addOutLine = CPDFOutline()
  159. addOutLine.label = String(format: "%@ %ld", KMLocalizedString("Page", nil), "\(self.listView.currentPageIndex + 1)")
  160. addOutLine.destination = self.listView.currentDestination
  161. self.addoutline(parent: grandfatherOutLine, addOutline: addOutLine, index: Int(fatherOutLine?.numberOfChildren ?? 0) + 1, needExpand: false)
  162. }
  163. }
  164. //移除节点
  165. @objc func outlineContextMenuItemClicked_RemoveEntry(_ sender: AnyObject?) {
  166. let set = self.selectedRowIndexes()
  167. var selectedPDFOutlineArr = NSMutableArray()
  168. for idx in set {
  169. selectedPDFOutlineArr.add(self.tocOutlineView.item(atRow: idx))
  170. }
  171. //整体移除多选
  172. for tOutline in selectedPDFOutlineArr {
  173. guard let outL = tOutline as? CPDFOutline else {
  174. continue
  175. }
  176. self.removeOutline(parent: outL.parent , removeOutline: outL, index: Int(outL.index), needExpand: false)
  177. }
  178. }
  179. //重置目的
  180. @objc func outlineContextMenuItemClicked_SetDestination(_ sender: AnyObject?) {
  181. guard let setPDFOutline = self.tocOutlineView.item(atRow: self.tocOutlineView.clickedRow) as? CPDFOutline else {
  182. return
  183. }
  184. Task {
  185. let modalRes = await KMAlertTool.runModel(style: .informational, message: KMLocalizedString("Are you sure you want to set the destination as the current location?", nil), buttons: [KMLocalizedString("Yes", nil), KMLocalizedString("No", nil)])
  186. if (modalRes == .alertFirstButtonReturn) {
  187. self.changePDFOutlineDestination(self.listView.currentDestination, PDFoutline: setPDFOutline)
  188. self.tocOutlineView.reloadData()
  189. let idx = self.tocOutlineView.row(forItem: setPDFOutline)
  190. self.tocOutlineView.selectRowIndexes(IndexSet(integer: idx), byExtendingSelection: false)
  191. }
  192. }
  193. }
  194. }