KMMainViewController+Action.swift 111 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423
  1. //
  2. // KMMainViewController+Action.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by wanjun on 2022/12/15.
  6. //
  7. import Foundation
  8. extension KMMainViewController {
  9. func search(searchString: String, isCase: Bool, display: Bool = true, needShowAll: Bool = false) {
  10. }
  11. func removeSignatures(signatures:[CPDFSignature]) {
  12. for signature in signatures {
  13. self.listView.document.removeSignature(signature)
  14. }
  15. for i in 0..<self.listView.document.pageCount {
  16. guard let page = self.listView.document.page(at: i) else {
  17. continue
  18. }
  19. let annotations : [CPDFAnnotation] = page.annotations
  20. for j in 0..<annotations.count {
  21. let annotation = annotations[j]
  22. if annotation is CPDFSignatureWidgetAnnotation {
  23. (annotation as! CPDFSignatureWidgetAnnotation).updateAppearanceStream()
  24. }
  25. }
  26. }
  27. self.listView.setNeedsDisplayForVisiblePages()
  28. let tSignatures : [CPDFSignature] = self.listView.document.signatures()
  29. var mSignatures : [CPDFSignature] = []
  30. for sign in tSignatures {
  31. if sign.signers.count > 0 {
  32. mSignatures.append(sign)
  33. }
  34. }
  35. }
  36. //MARK: menu菜单
  37. func addText() -> NSMenuItem {
  38. let addTextItem = NSMenuItem(title: NSLocalizedString("Add Text", comment: ""), action: #selector(addImageText), target: self, tag: 0)
  39. return addTextItem
  40. }
  41. func addImage() -> NSMenuItem {
  42. let addImageItem = NSMenuItem(title: NSLocalizedString("Add Image", comment: ""), action: #selector(addImageText), target: self, tag: 1)
  43. return addImageItem
  44. }
  45. func replaceImageArea()->NSMenuItem {
  46. let replaceItem = NSMenuItem(title: NSLocalizedString("Replace", comment: ""), action: #selector(menuItemEditingClick_ReplaceImage), target: self)
  47. return replaceItem
  48. }
  49. func exportImageArea()->NSMenuItem {
  50. let exportItem = NSMenuItem(title: NSLocalizedString("Export", comment: ""), action: #selector(menuItemEditingClick_ExportImage), target: self)
  51. let menu = NSMenu()
  52. let item1 = menu.insertItem(withTitle: NSLocalizedString("PNG", comment: ""), action:#selector(exportStampImage), target: self, tag:0, at: 0)
  53. let item2 = menu.insertItem(withTitle: NSLocalizedString("JPG", comment: ""), action:#selector(menuItemEditingClick_ExportImage), target: self, tag:1, at: 1)
  54. let item3 = menu.insertItem(withTitle: NSLocalizedString("PDF", comment: ""), action:#selector(exportStampImage), target: self, tag:2, at: 2)
  55. exportItem.submenu = menu
  56. return exportItem
  57. }
  58. func exportImageStampItem()->NSMenuItem {
  59. let exportItem = NSMenuItem(title: NSLocalizedString("Export", comment: ""), action: #selector(menuItemEditingClick_ExportImage), target: self)
  60. let menu = NSMenu()
  61. let item1 = menu.insertItem(withTitle: NSLocalizedString("PNG", comment: ""), action:#selector(exportStampImage), target: self, tag:0, at: 0)
  62. let item2 = menu.insertItem(withTitle: NSLocalizedString("PDF", comment: ""), action:#selector(exportStampImage), target: self, tag:2, at: 1)
  63. exportItem.submenu = menu
  64. return exportItem
  65. }
  66. func exportMenu() -> NSMenu {
  67. let menu = NSMenu()
  68. _ = menu.insertItem(withTitle: NSLocalizedString("PNG", comment: ""), action:#selector(exportCorpImage), target: self, tag:0, at: 0)
  69. _ = menu.insertItem(withTitle: NSLocalizedString("JPG", comment: ""), action:#selector(exportCorpImage), target: self, tag:1, at: 1)
  70. _ = menu.insertItem(withTitle: NSLocalizedString("PDF", comment: ""), action:#selector(exportCorpImage), target: self, tag:2, at: 2)
  71. return menu
  72. }
  73. func cropMenu() -> NSMenu {
  74. let menu = NSMenu()
  75. return menu
  76. }
  77. func zoomSelectionMenuItem() -> NSMenuItem {
  78. let item = NSMenuItem(title: NSLocalizedString("Zoom To Selection", comment: ""), action: #selector(doZoomToAutoSelection), target: self)
  79. return item
  80. }
  81. func enterAnnotationStype() -> NSMenuItem {
  82. let stypItem = NSMenuItem(title: NSLocalizedString("Annotate", comment: ""), action: nil, target: self)
  83. let stypeMenu = NSMenu()
  84. if listView.currentSelection != nil && listView.currentSelection.selectionType() == .text {
  85. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Highlight", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 0)
  86. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Underline", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 1)
  87. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Strikethrough", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2)
  88. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Squiggly", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2)
  89. stypeMenu.addItem(NSMenuItem.separator())
  90. }
  91. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Text Note", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 1)
  92. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Anchored Note", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 2)
  93. stypeMenu.addItem(NSMenuItem.separator())
  94. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Rectangle", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 3)
  95. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Circle", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 4)
  96. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Arrow", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 5)
  97. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Line", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 6)
  98. if viewManager.isPDFReadMode {
  99. } else {
  100. stypeMenu.addItem(NSMenuItem.separator())
  101. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Stamp", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 8)
  102. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Image", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 10)
  103. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Signature", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 9)
  104. }
  105. stypItem.submenu = stypeMenu
  106. if self.listView.annotationType == .ink {
  107. stypeMenu.item(withTitle: NSLocalizedString("Freehand", comment: ""))?.state = .on
  108. } else if self.listView.annotationType == .freeText {
  109. stypeMenu.item(withTitle: NSLocalizedString("Text Note", comment: ""))?.state = .on
  110. } else if self.listView.annotationType == .anchored {
  111. stypeMenu.item(withTitle: NSLocalizedString("Anchored Note", comment: ""))?.state = .on
  112. } else if self.listView.annotationType == .square {
  113. stypeMenu.item(withTitle: NSLocalizedString("Rectangle", comment: ""))?.state = .on
  114. } else if self.listView.annotationType == .circle {
  115. stypeMenu.item(withTitle: NSLocalizedString("Circle", comment: ""))?.state = .on
  116. } else if self.listView.annotationType == .arrow {
  117. stypeMenu.item(withTitle: NSLocalizedString("Arrow", comment: ""))?.state = .on
  118. } else if self.listView.annotationType == .line {
  119. stypeMenu.item(withTitle: NSLocalizedString("Line", comment: ""))?.state = .on
  120. } else if self.listView.annotationType == .link {
  121. stypeMenu.item(at: 7)?.state = .on
  122. } else if self.listView.annotationType == .stamp {
  123. stypeMenu.item(withTitle: NSLocalizedString("Stamp", comment: ""))?.state = .on
  124. } else if self.listView.annotationType == .signSignature {
  125. stypeMenu.item(withTitle: NSLocalizedString("Signature", comment: ""))?.state = .on
  126. }
  127. return stypItem
  128. }
  129. func setAnnotationToolStype() -> NSMenuItem {
  130. let stypItem = NSMenuItem(title: NSLocalizedString("Tool Mode", comment: ""), action: nil, target: self)
  131. let stypeMenu = NSMenu()
  132. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Text", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.CTextToolMode.rawValue)
  133. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Scroll", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.CMoveToolMode.rawValue)
  134. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Magnify", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.CMagnifyToolMode.rawValue)
  135. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Select", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.CSelectToolMode.rawValue)
  136. stypeMenu.insertItem(NSMenuItem.separator(), at: 4)
  137. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Highlight", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.highlight.rawValue)
  138. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Underline", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.underline.rawValue)
  139. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Strikethrough", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.strikeOut.rawValue)
  140. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Squiggly", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.squiggly.rawValue)
  141. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Freehand", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.ink.rawValue)
  142. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Text Note", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.freeText.rawValue)
  143. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Anchored Note", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.anchored.rawValue)
  144. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Rectangle", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.square.rawValue)
  145. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Circle", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.circle.rawValue)
  146. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Arrow", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.arrow.rawValue)
  147. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Line", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.line.rawValue)
  148. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Link", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.link.rawValue)
  149. stypItem.submenu = stypeMenu
  150. return stypItem
  151. }
  152. func addReadModelStype() -> NSMenuItem {
  153. var stypItem = NSMenuItem(title: NSLocalizedString("Read Mode On", comment: ""), action: #selector(openPDFReadMode), target: self)
  154. if viewManager.isPDFReadMode {
  155. stypItem = NSMenuItem(title: NSLocalizedString("Read Mode Off", comment: ""), action: #selector(exitPDFReadMode), target: self)
  156. }
  157. return stypItem
  158. }
  159. func addOutlineStype() -> NSMenuItem {
  160. let stypItem = NSMenuItem(title: NSLocalizedString("Add Outline Item", comment: ""), action: #selector(addOutLineItemAction), target: self)
  161. return stypItem
  162. }
  163. func setTTSStype() -> NSMenuItem {
  164. let stypItem = NSMenuItem(title: NSLocalizedString("TTS", comment: ""), action: nil , target: self)
  165. return stypItem
  166. }
  167. func setShareStype() -> NSMenuItem {
  168. let stypItem = NSMenuItem(title: NSLocalizedString("Share", comment: ""), action: nil, target: self)
  169. var string = ""
  170. if listView.activeAnnotation != nil {
  171. string = self.listView.activeAnnotation?.contents ?? ""
  172. }
  173. if string.count < 1{
  174. string = self.listView.currentSelection?.string() ?? ""
  175. }
  176. stypItem.submenu = NSSharingServicePicker.menu(forSharingItems: [string], subjectContext: "", withTarget: self, selector: #selector(shareFromService), serviceDelegate: nil)
  177. return stypItem
  178. }
  179. func numberOfChars(_ str: String) -> (num: Int, indexN: Int) {
  180. var number = 0
  181. var indexN = 0
  182. guard str.count > 0 else {return (0, 0)}
  183. for i in 0...str.count - 1 {
  184. let c: unichar = (str as NSString).character(at: i)
  185. if (c >= 0x4E00) {
  186. number += 2
  187. }else {
  188. number += 1
  189. }
  190. if number > 56{
  191. indexN = i
  192. number = 100
  193. break
  194. }
  195. }
  196. return (number, indexN)
  197. }
  198. func setLookUpStype() -> NSMenuItem {
  199. guard let str = listView.currentSelection?.string() else {
  200. return NSMenuItem.separator()
  201. }//String(format: "Look Up %@", listView.currentSelection?.string() ?? "")
  202. let dic = numberOfChars(str)
  203. var newStr = str
  204. if dic.num == 100{
  205. newStr = str.prefix(dic.indexN) + "..."
  206. }
  207. newStr = NSLocalizedString("Look Up ", comment: "") + "\"" + newStr + "\""
  208. let stypItem = NSMenuItem(title: newStr, action: #selector(lookUpAction), target: self)
  209. return stypItem
  210. }
  211. func setSearchBaiduStype() -> NSMenuItem {
  212. let stypItem = NSMenuItem(title: NSLocalizedString("Search with Baidu", comment: ""), action: #selector(searchBaiduAction), target: self)
  213. return stypItem
  214. }
  215. func setCutStype() -> NSMenuItem {
  216. let stypItem = NSMenuItem(title: NSLocalizedString("Cut", comment: ""), action: #selector(cutAction), target: self)
  217. return stypItem
  218. }
  219. func setDeleteStype() -> NSMenuItem {
  220. let stypItem = NSMenuItem(title: NSLocalizedString("Delete", comment: ""), action: #selector(deleteAction), target: self)
  221. return stypItem
  222. }
  223. func setColorsStype() -> NSMenuItem {
  224. let stypItem = NSMenuItem(title: NSLocalizedString("Colors", comment: ""), action: #selector(ColorsItemAction), target: self)
  225. return stypItem
  226. }
  227. func setLinesStype() -> NSMenuItem {
  228. let stypItem = NSMenuItem(title: NSLocalizedString("Lines", comment: ""), action: #selector(LinesItemAction), target: self)
  229. return stypItem
  230. }
  231. func setEditNoteStype() -> NSMenuItem {
  232. let stypItem = NSMenuItem(title: NSLocalizedString("Edit Note", comment: ""), action: #selector(EditNoteItemAction), target: self)
  233. return stypItem
  234. }
  235. func setRotateStype() -> NSMenuItem {
  236. let stypItem = NSMenuItem(title: NSLocalizedString("Rotate", comment: ""), action: nil, target: self)
  237. let stypeMenu = NSMenu()
  238. let item1 = stypeMenu.addItem(withTitle: NSLocalizedString("Rotate Left", comment: ""), action: #selector(rotateLeftAction), target: self, tag: 0)
  239. let item2 = stypeMenu.addItem(withTitle: NSLocalizedString("Rotate Right", comment: ""), action: #selector(rotateRightAction), target: self, tag: 1)
  240. stypItem.submenu = stypeMenu
  241. return stypItem
  242. }
  243. func setNextPageStype() -> NSMenuItem {
  244. let stypItem = NSMenuItem(title: NSLocalizedString("Next Page", comment: ""), action: #selector(NextPageAction), target: self)
  245. stypItem.isEnabled = false
  246. if listView.canGoToNextPage() {
  247. stypItem.isEnabled = true
  248. }
  249. return stypItem
  250. }
  251. func setPreviousPageStype() -> NSMenuItem {
  252. let stypItem = NSMenuItem(title: NSLocalizedString("Previous Page", comment: ""), action: #selector(PreviousPageAction), target: self)
  253. stypItem.isEnabled = false
  254. if listView.canGoToPreviousPage() {
  255. stypItem.isEnabled = true
  256. }
  257. return stypItem
  258. }
  259. func setTranslateStype() -> NSMenuItem {
  260. let str = listView.currentSelection?.string() ?? ""//String(format: "Translate %@", listView.currentSelection?.string() ?? "")
  261. let dic = numberOfChars(str)
  262. var newStr = str
  263. if dic.num == 100{
  264. newStr = str.prefix(dic.indexN) + "..."
  265. }
  266. newStr = NSLocalizedString("Translate", comment: "") + " \"" + newStr + "\""
  267. let stypItem = NSMenuItem(title: newStr, action: #selector(TranslateItemAction), target: self)
  268. return stypItem
  269. }
  270. func setAutoScrollStype() -> NSMenuItem {
  271. let stypItem = NSMenuItem(title: NSLocalizedString("Auto Scroll", comment: ""), action: #selector(AutoScrollItemAction), target: self)
  272. stypItem.state = self.listView.isAutoFlow() ? .on : .off
  273. return stypItem
  274. }
  275. func setSnapshotStype() -> NSMenuItem {
  276. let stypItem = NSMenuItem(title: NSLocalizedString("Snapshot", comment: ""), action: nil, target: self)
  277. let stypeMenu = NSMenu()
  278. let item1 = stypeMenu.addItem(withTitle: NSLocalizedString("Auto", comment: ""), action: #selector(takeSnapshot), target: self, tag: 0)
  279. let item2 = stypeMenu.addItem(withTitle: NSLocalizedString("Select Area", comment: ""), action: #selector(takeSnapshotSelectContent), target: self, tag: 1)
  280. stypItem.submenu = stypeMenu
  281. return stypItem
  282. }
  283. func setServicesStype() -> NSMenuItem {
  284. let stypItem = NSMenuItem(title: NSLocalizedString("Services", comment: ""), action: nil, target: self)
  285. let stypeMenu = NSMenu()
  286. let item1 = stypeMenu.addItem(withTitle: NSLocalizedString("Add to Music as a Spoken Track", comment: ""), action: #selector(AddtoMusicasASpokenTrack), target: self, tag: 0)
  287. let item2 = stypeMenu.addItem(withTitle: NSLocalizedString("Convert Text to Simplified Chinese", comment: ""), action: #selector(ConvertTextToSimplifiedChinese), target: self, tag: 1)
  288. let item3 = stypeMenu.addItem(withTitle: NSLocalizedString("Convert Text to Traditional Chinese", comment: ""), action: #selector(ConvertTextToTraditionalChinese), target: self, tag: 2)
  289. let item4 = stypeMenu.addItem(withTitle: NSLocalizedString("Open", comment: ""), action: #selector(OpenItemAction), target: self, tag: 3)
  290. let item5 = stypeMenu.addItem(withTitle: NSLocalizedString("Search With Baidu", comment: ""), action: #selector(searchBaiduAction), target: self, tag: 4)
  291. let item6 = stypeMenu.addItem(withTitle: NSLocalizedString("Show in Finder", comment: ""), action: #selector(showInFinder), target: self, tag: 4)
  292. let item7 = stypeMenu.addItem(withTitle: NSLocalizedString("Show Info in Finder", comment: ""), action: #selector(showInfoInFinder), target: self, tag: 5)
  293. stypItem.submenu = stypeMenu
  294. return stypItem
  295. }
  296. func setCropStype() -> NSMenuItem {
  297. let stypItem = NSMenuItem(title: NSLocalizedString("Crop", comment: ""), action: nil, target: self)
  298. let stypeMenu = NSMenu()
  299. if NSIsEmptyRect(listView.selectionRect){
  300. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Select Area", comment: ""), action: #selector(selectToolModel), target: self, tag: 4)
  301. _ = stypeMenu.addItem(withTitle: NSLocalizedString("Crop Options...", comment: ""), action: #selector(customCropModel), target: self, tag: 5)
  302. }
  303. stypItem.submenu = stypeMenu
  304. return stypItem
  305. }
  306. func setAITranslateStype() -> NSMenuItem {
  307. let stypItem = NSMenuItem(title: NSLocalizedString("AI Translate", comment: ""), action: #selector(AITranslateItemAction), target: self)
  308. stypItem.state = self.listView.isAutoFlow() ? .on : .off
  309. return stypItem
  310. }
  311. func setAIProofreadStype() -> NSMenuItem {
  312. let stypItem = NSMenuItem(title: NSLocalizedString("AI Proofread", comment: ""), action: #selector(AIProofreadItemAction), target: self)
  313. stypItem.state = self.listView.isAutoFlow() ? .on : .off
  314. return stypItem
  315. }
  316. func setAIRewriteStype() -> NSMenuItem {
  317. let stypItem = NSMenuItem(title: NSLocalizedString("AI Rewrite", comment: ""), action: #selector(AIRewriteItemAction), target: self)
  318. stypItem.state = self.listView.isAutoFlow() ? .on : .off
  319. return stypItem
  320. }
  321. func addHighlightLinksStype() -> NSMenuItem {
  322. let highlightLink = KMPreferenceManager.shared.highlightLinks
  323. var highlightLinkTitle = NSLocalizedString("Highlight Links", comment: "")
  324. if highlightLink {
  325. highlightLinkTitle = NSLocalizedString("Disable Highlight Links", comment: "")
  326. }
  327. let highlightLinksItem = NSMenuItem(title: highlightLinkTitle, action: #selector(highlightLinks), target: self)
  328. return highlightLinksItem
  329. }
  330. func addAnnotationForStyleMenu(_ item: NSMenuItem?) {
  331. if item == nil {
  332. return
  333. }
  334. let menu = NSMenu()
  335. item?.submenu = menu
  336. let height = NSMenuItem(title: NSLocalizedString("Highlight", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 0)
  337. let underline = NSMenuItem(title: NSLocalizedString("Underline", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 1)
  338. let strickout = NSMenuItem(title: NSLocalizedString("Strikethrough", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2)
  339. let wavyLine = NSMenuItem(title: NSLocalizedString("Squiggly", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2)
  340. let text = NSMenuItem(title: NSLocalizedString("Text", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 3)
  341. let note = NSMenuItem(title: NSLocalizedString("Note", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 4)
  342. let rectangle = NSMenuItem(title: NSLocalizedString("Rectangle", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 5)
  343. let oval = NSMenuItem(title: NSLocalizedString("Oval", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 6)
  344. let line = NSMenuItem(title: NSLocalizedString("Line", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 7)
  345. let link = NSMenuItem(title: NSLocalizedString("Add Link", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 8)
  346. let outline = NSMenuItem(title: NSLocalizedString("Add Outline", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 9)
  347. menu.insertItem(NSMenuItem.separator(), at: menu.items.count)
  348. if listView.currentSelection.selectionType() != .image {
  349. menu.insertItem(height, at: menu.items.count)
  350. menu.insertItem(underline, at: menu.items.count)
  351. menu.insertItem(strickout, at: menu.items.count)
  352. menu.insertItem(wavyLine, at: menu.items.count)
  353. menu.insertItem(NSMenuItem.separator(), at: menu.items.count)
  354. }
  355. if viewManager.isPDFReadMode {
  356. } else {
  357. if listView.currentSelection.selectionType() != .image &&
  358. listView.currentSelection.selectionType() != .text {
  359. menu.insertItem(text, at: menu.items.count)
  360. menu.insertItem(note, at: menu.items.count)
  361. }
  362. }
  363. if viewManager.isPDFReadMode {
  364. } else {
  365. if listView.currentSelection.selectionType() != .image {
  366. menu.insertItem(NSMenuItem.separator(), at: menu.items.count)
  367. menu.insertItem(rectangle, at: menu.items.count)
  368. menu.insertItem(oval, at: menu.items.count)
  369. }
  370. }
  371. if viewManager.isPDFReadMode {
  372. } else {
  373. if listView.currentSelection.selectionType() != .image &&
  374. listView.currentSelection.selectionType() != .text {
  375. menu.insertItem(line, at: menu.items.count)
  376. }
  377. }
  378. menu.insertItem(NSMenuItem.separator(), at: menu.items.count)
  379. if viewManager.isPDFReadMode {
  380. } else {
  381. menu.insertItem(link, at: menu.items.count)
  382. }
  383. if viewManager.isPDFReadMode {
  384. } else {
  385. if listView.currentSelection.selectionType() != .image {
  386. menu.insertItem(outline, at: menu.items.count)
  387. }
  388. }
  389. menu.insertItem(NSMenuItem.separator(), at: menu.items.count)
  390. if viewManager.isPDFReadMode {
  391. } else {
  392. if (listView.currentSelection.selectionType() != .image) {
  393. }
  394. }
  395. menu.insertItem(NSMenuItem.separator(), at: menu.items.count)
  396. }
  397. func addBookmarkMenu() -> NSMenuItem {
  398. if self.listView.document.bookmark(forPageIndex: UInt(self.listView.currentPageIndex)) == nil {
  399. let bookMarkItem = NSMenuItem(title: NSLocalizedString("Add Bookmark", comment: ""), action: #selector(menuItemBookMarkClick_add), target: self)
  400. return bookMarkItem
  401. } else {
  402. let bookMarkItem = NSMenuItem(title: NSLocalizedString("Remove Bookmark", comment: ""), action: #selector(menuItemBookMarkClick_add), target: self)
  403. return bookMarkItem
  404. }
  405. }
  406. func findStringMenu() -> NSMenuItem {
  407. let menuItem = NSMenuItem(title: NSLocalizedString("Find", comment: ""), action: #selector(menuItemAnnotationClick_FindString), target: self)
  408. menuItem.keyEquivalent = "f"
  409. return menuItem
  410. }
  411. func printingMenu() -> NSMenuItem {
  412. let menuItem = NSMenuItem(title: NSLocalizedString("Print", comment: ""), action: #selector(menuItemAnnotationClick_Print), keyEquivalent: "p")
  413. return menuItem
  414. }
  415. func fontSizes()->NSArray {
  416. return ["6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "24", "36", "48", "72", "96", "144", "288"]
  417. }
  418. func handleRightMouseDown(theEvent: NSEvent) -> Bool {
  419. if interactionMode == .presentation {
  420. listView.goToPreviousPage(nil)
  421. return true
  422. }
  423. return false
  424. }
  425. func useNativeFullScreen() -> Bool {
  426. var isFull = false
  427. let sel = NSSelectorFromString("toggleFullscreen:")
  428. if NSWindow.instancesRespond(to: sel) && UserDefaults.standard.bool(forKey: "SKUseLegacyFullScreenKey"){
  429. isFull = true
  430. }
  431. return isFull
  432. }
  433. func forceSubwindowsOnTop(_ flag: Bool) {
  434. }
  435. //MARK: menuItem Action
  436. @objc func menuItemEditingClick_FontColor(sender: NSMenuItem) {
  437. let color = listView.editingSelectionFontColor()
  438. let panel = NSColorPanel.shared
  439. panel.setTarget(self)
  440. panel.setAction(#selector(fontColorChangeAction))
  441. panel.orderFront(nil)
  442. panel.showsAlpha = false
  443. panel.color = color ?? NSColor.black
  444. }
  445. @objc func fontColorChangeAction(sender: NSColorPanel) {
  446. self.listView.setEditingSelectionFontColor(sender.color)
  447. }
  448. @objc func menuItemEditingClick_FontSize(sender: NSMenuItem) {
  449. let fontSize = self.fontSizes().object(at: sender.tag)
  450. self.listView.setEditingSelectionFontSize(CGFloat(Int(fontSize as! String)!))
  451. }
  452. @objc func addImageText(sender: NSMenuItem) {
  453. let event = NSApp.currentEvent
  454. let clickLocation = event?.locationInWindow
  455. var point = self.listView.convert(clickLocation!, from: NSApp.mainWindow?.contentView)
  456. var point2 = self.listView.convert(point, to: self.listView.currentPage())
  457. point2 = CGPoint(x: self.listView.bounds.width - point2.x, y: self.listView.bounds.height - point2.y)
  458. point = point2
  459. if sender.tag == 0 {
  460. KMPrint("添加文字")
  461. } else if sender.tag == 1 {
  462. } else if sender.tag == 2 {
  463. KMPrint("粘贴")
  464. }
  465. }
  466. @objc func menuItemEditingClick_CropImage(sender: NSMenuItem) {
  467. if self.listView.cropAreas != nil && self.listView.selectImageAreas != nil{
  468. self.listView.cropEditImageArea(self.listView.selectImageAreas, withBounds: self.listView.cropAreas.cropRect)
  469. }
  470. }
  471. @objc func menuItemEditingClick_CancelCrop(sender: NSMenuItem) {
  472. self.listView.exitCrop(with: self.listView.selectImageAreas)
  473. self.listView.cropAreas = nil
  474. self.listView.isEditImage = false
  475. }
  476. @objc func menuItemEditingClick_RestoreCrop(sender: NSMenuItem) {
  477. self.listView.resetCrop(with: self.listView.selectImageAreas)
  478. }
  479. @objc func menuItemEditingClick_CutImage(sender: NSMenuItem) {
  480. }
  481. @objc func menuItemEditingClick_ReplaceImage(sender: NSMenuItem) {
  482. if self.listView.selectImageAreas == nil {
  483. return
  484. }
  485. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Replace"])
  486. let panel = NSOpenPanel()
  487. panel.allowsMultipleSelection = false
  488. panel.allowedFileTypes = ["png","jpg"]
  489. panel.beginSheetModal(for: NSApp.mainWindow!) { response in
  490. if response == .OK {
  491. let openPath = panel.url?.path
  492. let s = self.listView.replace(self.listView.selectImageAreas, imagePath: openPath!)
  493. if s {
  494. }
  495. }
  496. }
  497. }
  498. @objc func menuItemEditingClick_ExportImage(sender: NSMenuItem) {
  499. if self.listView.selectImageAreas == nil {
  500. return
  501. }
  502. let panel = NSSavePanel()
  503. panel.nameFieldStringValue = "\(NSLocalizedString("Untitled", comment: "")).jpg"
  504. panel.isExtensionHidden = true
  505. let response = panel.runModal()
  506. if response == .OK {
  507. let url = panel.url
  508. if FileManager.default.fileExists(atPath: url!.path) {
  509. try?FileManager.default.removeItem(atPath: url!.path)
  510. }
  511. let result = self.listView.extractImage(with: self.listView.selectImageAreas, toImagePath: url!.path)
  512. if result {
  513. NSWorkspace.shared.activateFileViewerSelecting([url!])
  514. }
  515. }
  516. }
  517. @objc func AddtoMusicasASpokenTrack(sender: NSMenuItem) {
  518. }
  519. @objc func ConvertTextToSimplifiedChinese(sender: NSMenuItem) {
  520. }
  521. @objc func ConvertTextToTraditionalChinese(sender: NSMenuItem) {
  522. }
  523. @objc func OpenItemAction(sender: NSMenuItem) {
  524. }
  525. @objc func customCropModel(sender: NSMenuItem) {
  526. }
  527. @objc func rotateRightAction(sender: NSMenuItem) {
  528. }
  529. @objc func rotateLeftAction(sender: NSMenuItem) {
  530. }
  531. @objc func menuItemAnnotationClick_toolModel(sender: NSMenuItem) {
  532. self.listView.toolMode = .CNoteToolMode
  533. var identifier = KMDocumentAnnotationToolbarItemIdentifier
  534. var model : KMToolbarViewType = .None
  535. switch sender.tag {
  536. case 0:
  537. identifier = KMDocumentAnnotationToolbarItemIdentifier
  538. model = .Annatiton
  539. case 1:
  540. identifier = KMToolbarMoveToolModeItemIdentifier
  541. model = .Move
  542. case 2:
  543. identifier = KMToolbarMagnifyToolModeItemIdentifier
  544. model = .Magnify
  545. case 3:
  546. identifier = KMToolbarSelectToolModeItemIdentifier
  547. model = .Select
  548. case 4:
  549. identifier = KMToolbarZoomToSelectionItemIdentifier
  550. model = .SelectZoom
  551. default:
  552. break
  553. }
  554. }
  555. @objc func changeAnnotationMode_itemAction(sender : NSMenuItem) {
  556. var itemId: String?
  557. if sender.tag == CAnnotationType.highlight.rawValue {
  558. itemId = KMToolbarHighlightAnnotationItemIdentifier
  559. } else if sender.tag == CAnnotationType.underline.rawValue {
  560. itemId = KMToolbarUnderlineAnnotationItemIdentifier
  561. } else if sender.tag == CAnnotationType.strikeOut.rawValue {
  562. itemId = KMToolbarStrikeOutAnnotationItemIdentifier
  563. } else if sender.tag == CAnnotationType.squiggly.rawValue {
  564. itemId = KMToolbarSquigglyAnnotationItemIdentifier
  565. } else if sender.tag == CAnnotationType.ink.rawValue {
  566. itemId = KMToolbarInkAnnotationItemIdentifier
  567. } else if sender.tag == CAnnotationType.freeText.rawValue {
  568. itemId = KMToolbarFreeTextAnnotationItemIdentifier
  569. } else if sender.tag == CAnnotationType.anchored.rawValue {
  570. itemId = KMToolbarAnchoredAnnotationItemIdentifier
  571. } else if sender.tag == CAnnotationType.square.rawValue {
  572. itemId = KMToolbarSquareAnnotationItemIdentifier
  573. } else if sender.tag == CAnnotationType.circle.rawValue {
  574. itemId = KMToolbarCircleAnnotationItemIdentifier
  575. } else if sender.tag == CAnnotationType.arrow.rawValue {
  576. itemId = KMToolbarArrowAnnotationItemIdentifier
  577. } else if sender.tag == CAnnotationType.line.rawValue {
  578. itemId = KMToolbarLineAnnotationItemIdentifier
  579. } else if sender.tag == CAnnotationType.link.rawValue {
  580. itemId = KMToolbarLinkAnnotationItemIdentifier
  581. }
  582. }
  583. @objc func menuItemAnnotationClick_add(sender : NSMenuItem) {
  584. var annotationType : CAnnotationType = .unkown
  585. switch sender.tag {
  586. case 0:
  587. annotationType = .highlight
  588. case 1:
  589. annotationType = .underline
  590. case 2:
  591. if sender.title == NSLocalizedString("Squiggly", comment: "") {
  592. annotationType = .squiggly
  593. } else {
  594. annotationType = .strikeOut
  595. }
  596. case 3:
  597. annotationType = .freeText
  598. case 4:
  599. annotationType = .anchored
  600. case 5:
  601. annotationType = .square
  602. case 6:
  603. annotationType = .circle
  604. case 7:
  605. annotationType = .line
  606. case 8:
  607. annotationType = .link
  608. case 9:
  609. return
  610. case 10:
  611. annotationType = .unkown
  612. default:
  613. break
  614. }
  615. if (annotationType != .link) {
  616. self.listView.addAnnotation(with: annotationType, selection: self.listView.currentSelection, page: self.listView.currentSelection.page, bounds: self.listView.currentSelection.bounds)
  617. self.listView.currentSelection = nil;
  618. return
  619. }
  620. // link
  621. let selection = self.listView.currentSelection
  622. DispatchQueue.main.async {
  623. Task { @MainActor in
  624. let annotation = self.listView.addAnnotation(with: annotationType, selection: selection, page: selection?.page, bounds: selection!.bounds)
  625. self.listView.currentSelection = nil;
  626. if (annotation != nil) {
  627. self.listView.updateActiveAnnotations([annotation!])
  628. }
  629. }
  630. }
  631. }
  632. @objc func menuItemAnnotationClick_addStype(sender: NSMenuItem) {
  633. Task { @MainActor in
  634. let idx = sender.tag
  635. if idx == 10 {
  636. if IAPProductsManager.default().isAvailableAllFunction() == false {
  637. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  638. return
  639. }
  640. }
  641. var point = mouseRightMenuEvent?.locationInWindow
  642. if (point == nil) {
  643. point = NSZeroPoint
  644. }
  645. let currentPoint: NSPoint = self.listView.convert(point!, from: self.listView.superview)
  646. let currentPage = self.listView.page(for: currentPoint, nearest: true)
  647. var pagePoint = self.listView.convert(currentPoint, to: currentPage)
  648. var annotation: CPDFAnnotation?
  649. if viewManager.isPDFReadMode {
  650. if (sender.tag == 0 || sender.tag == 7 || sender.tag == 8 || sender.tag == 9) { // Ink & Link & stamp & sign
  651. self.listView.toolMode = .CNoteToolMode
  652. }
  653. switch sender.tag {
  654. case 0:
  655. self.listView.annotationType = CAnnotationType.ink
  656. case 1:
  657. let defaultSize = self.listView.defaultSize(with: .freeText, in: currentPage)
  658. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  659. annotation = self.listView.addAnnotation(with: .freeText, selection: nil, page: currentPage, bounds: bounds)
  660. if ((annotation) != nil) {
  661. self.listView.updateActiveAnnotations([annotation!])
  662. self.listView.edit(annotation)
  663. }
  664. case 2:
  665. let defaultSize = self.listView.defaultSize(with: .anchored, in: currentPage)
  666. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  667. annotation = self.listView.addAnnotation(with: .anchored, selection: nil, page: currentPage, bounds: bounds)
  668. self.listView.edit(annotation)
  669. case 3:
  670. let defaultSize = self.listView.defaultSize(with: .square, in: currentPage)
  671. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  672. annotation = self.listView.addAnnotation(with: .square, selection: nil, page: currentPage, bounds: bounds)
  673. case 4:
  674. let defaultSize = self.listView.defaultSize(with: .circle, in: currentPage)
  675. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  676. annotation = self.listView.addAnnotation(with: .circle, selection: nil, page: currentPage, bounds: bounds)
  677. case 5:
  678. let defaultSize = self.listView.defaultSize(with: .arrow, in: currentPage)
  679. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  680. annotation = self.listView.addAnnotation(with: .arrow, selection: nil, page: currentPage, bounds: bounds)
  681. case 6:
  682. let defaultSize = self.listView.defaultSize(with: .line, in: currentPage)
  683. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  684. annotation = self.listView.addAnnotation(with: .line, selection: nil, page: currentPage, bounds: bounds)
  685. case 7:
  686. self.listView.annotationType = CAnnotationType.link
  687. toggleOpenRightSide()
  688. case 8:
  689. self.listView.annotationType = CAnnotationType.stamp
  690. toggleOpenRightSide()
  691. case 9:
  692. self.listView.annotationType = CAnnotationType.signSignature
  693. toggleOpenRightSide()
  694. default:
  695. break
  696. }
  697. } else {
  698. if (sender.tag == 7 || sender.tag == 8 || sender.tag == 9) { // Ink & Link & stamp & sign
  699. self.listView.toolMode = .CNoteToolMode
  700. }
  701. switch sender.tag {
  702. case 0:
  703. self.listView.toolMode = .CNoteToolMode
  704. self.listView.annotationType = CAnnotationType.ink
  705. case 1:
  706. let defaultSize = self.listView.defaultSize(with: .freeText, in: currentPage)
  707. if (pagePoint.x - defaultSize.width > 0){
  708. pagePoint.x -= defaultSize.width;
  709. }else{
  710. pagePoint.x = 0;
  711. }
  712. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  713. annotation = self.listView.addAnnotation(with: .freeText, selection: nil, page: currentPage, bounds: bounds)
  714. if ((annotation) != nil) {
  715. self.listView.edit(annotation)
  716. }
  717. case 2:
  718. let defaultSize = self.listView.defaultSize(with: .anchored, in: currentPage)
  719. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  720. annotation = self.listView.addAnnotation(with: .anchored, selection: nil, page: currentPage, bounds: bounds)
  721. self.listView.edit(annotation)
  722. case 3:
  723. let defaultSize = self.listView.defaultSize(with: .square, in: currentPage)
  724. if (pagePoint.x - defaultSize.width > 0){
  725. pagePoint.x -= defaultSize.width;
  726. }else{
  727. pagePoint.x = 0;
  728. }
  729. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  730. annotation = self.listView.addAnnotation(with: .square, selection: nil, page: currentPage, bounds: bounds)
  731. case 4:
  732. let defaultSize = self.listView.defaultSize(with: .circle, in: currentPage)
  733. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  734. annotation = self.listView.addAnnotation(with: .circle, selection: nil, page: currentPage, bounds: bounds)
  735. case 5:
  736. let defaultSize = self.listView.defaultSize(with: .arrow, in: currentPage)
  737. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  738. annotation = self.listView.addAnnotation(with: .arrow, selection: nil, page: currentPage, bounds: bounds)
  739. case 6:
  740. let defaultSize = self.listView.defaultSize(with: .line, in: currentPage)
  741. let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize)
  742. annotation = self.listView.addAnnotation(with: .line, selection: nil, page: currentPage, bounds: bounds)
  743. case 7:
  744. self.listView.annotationType = CAnnotationType.link
  745. toggleOpenRightSide()
  746. case 8:
  747. self.listView.annotationType = CAnnotationType.stamp
  748. toggleOpenRightSide()
  749. case 9:
  750. self.listView.annotationType = CAnnotationType.signSignature
  751. toggleOpenRightSide()
  752. case 10:
  753. self.addImgAnnotationToView(center: pagePoint)
  754. default:
  755. break
  756. }
  757. if annotation != nil{
  758. self.listView.activeAnnotations.removeAllObjects()
  759. var newAnnonations : [CPDFAnnotation] = []
  760. newAnnonations.append(annotation!)
  761. self.listView.updateActiveAnnotations(newAnnonations)
  762. }
  763. }
  764. }
  765. }
  766. func addImgAnnotationToView(center: NSPoint) {
  767. let accessoryCtr = KMImageAccessoryController()
  768. let openPanel = NSOpenPanel()
  769. openPanel.allowedFileTypes = KMImageAccessoryController.supportedImageTypes()
  770. openPanel.allowsMultipleSelection = false
  771. openPanel.accessoryView = accessoryCtr.view
  772. openPanel.isAccessoryViewDisclosed = true
  773. openPanel.beginSheetModal(for: self.view.window!) { result in
  774. if result == .OK {
  775. let fileURL = openPanel.urls.first
  776. let filePath = fileURL!.path
  777. if filePath.pathExtension == "pdf" {
  778. let pdf = CPDFDocument(url: fileURL)
  779. if pdf!.isEncrypted {
  780. NSSound.beep()
  781. return
  782. }
  783. }
  784. let img = NSImage(contentsOfFile: filePath)
  785. let isRemoveBGColor = accessoryCtr.selectedButton.state == .on
  786. self.listView.addImageAnnotation(img, center: center, isRemoveBGColor: isRemoveBGColor)
  787. }
  788. }
  789. }
  790. @objc func menuItemAnnotationClick_FindString(sender:NSMenuItem) {
  791. }
  792. @objc func menuItemAnnotationClick_Print(sender:NSMenuItem) {
  793. let rect = listView.currentSelectionRect()
  794. let page = listView.currentPage()
  795. let copyPage : CPDFPage = page!.copy() as! CPDFPage
  796. copyPage.setBounds(rect, for: .cropBox)
  797. let image : NSImage = copyPage.thumbnail(of:(copyPage.bounds(for: .cropBox)).size)
  798. // 执行右键操作后,需要取消框选区域
  799. if self.listView.toolMode == .CSelectToolMode {
  800. objc_sync_enter(self)
  801. self.listView.selectionRect = NSZeroRect
  802. self.listView.selectionPageIndex = UInt(NSNotFound)
  803. objc_sync_exit(self)
  804. }
  805. if (self.listView.document != nil && !self.listView.document.allowsPrinting) { // 有打印限制
  806. KMPasswordInputWindow.openWindow(window: self.view.window!, type: .owner, url: self.listView.document.documentURL) { [weak self] result ,password in
  807. if (result == .cancel) {
  808. return
  809. }
  810. // 解除权限
  811. self?.model.isSaveKeyChain = false
  812. self?.listView.document.unlock(withPassword: password)
  813. // 隐藏提示
  814. self?.hiddenSecureLimitTip()
  815. // 去打印
  816. KMPrintWindowController.printImage(image: image)
  817. }
  818. return
  819. }
  820. KMPrintWindowController.printImage(image: image)
  821. }
  822. // MARK: - Measure
  823. @objc func menuItemActionMeasureProperty(sender: NSMenuItem) {
  824. guard let anno = sender.representedObject as? CPDFAnnotation else {
  825. return
  826. }
  827. if distanceMeasureInfoWindowController?.window?.isVisible == true {
  828. distanceMeasureInfoWindowController?.hideFloatingWindow()
  829. } else if perimeterMeasureInfoWindowController?.window?.isVisible == true {
  830. perimeterMeasureInfoWindowController?.hideFloatingWindow()
  831. } else if areaMeasureInfoWindowController?.window?.isVisible == true {
  832. areaMeasureInfoWindowController?.hideFloatingWindow()
  833. }
  834. self.listView.updateActiveAnnotations([anno])
  835. self.pdfListViewChangeatioActiveAnnotations(self.listView, forActiveAnnotations: [anno], isRightMenu: false)
  836. self.listView.setNeedsDisplayForVisiblePages()
  837. }
  838. @objc func menuItemActionMeasureEditNote(sender: NSMenuItem) {
  839. guard let anno = sender.representedObject as? CPDFAnnotation else {
  840. return
  841. }
  842. self.listView.edit(anno)
  843. }
  844. @objc func menuItemActionMeasureSetting(sender: NSMenuItem) {
  845. guard let anno = sender.representedObject as? CPDFAnnotation else {
  846. return
  847. }
  848. self.listView.updateActiveAnnotations([anno])
  849. self.listView.setNeedsDisplayForVisiblePages()
  850. if let data = anno as? CPDFLineAnnotation, data.isMeasure {
  851. self.showMeasureDistanceSettingWindow(measureInfo: data.measureInfo)
  852. } else if let data = anno as? CPDFPolylineAnnotation {
  853. self.showMeasurePerimeterSettingWindow(measureInfo: data.measureInfo)
  854. } else if let data = anno as? CPDFPolygonAnnotation {
  855. self.showMeasureAreaSettingWindow(measureInfo: data.measureInfo)
  856. }
  857. }
  858. @objc func menuItemActionMeasureDelete(sender: NSMenuItem) {
  859. guard let anno = sender.representedObject as? CPDFAnnotation else {
  860. return
  861. }
  862. self.listView.remove(anno)
  863. }
  864. func showMeasureDistanceSettingWindow(measureInfo: CPDFDistanceMeasureInfo?, hideInfoWindow: Bool = true) {
  865. guard let mInfo = measureInfo else {
  866. return
  867. }
  868. let winC = CDistanceSettingWindowController(distanceMeasureInfo: mInfo)
  869. if hideInfoWindow {
  870. self.distanceMeasureInfoWindowController?.hideFloatingWindow()
  871. }
  872. winC.delegate = self
  873. winC.startModal("")
  874. }
  875. func showMeasurePerimeterSettingWindow(measureInfo: CPDFPerimeterMeasureInfo?, hideInfoWindow: Bool = true) {
  876. guard let mInfo = measureInfo else {
  877. return
  878. }
  879. let winC = CDistanceSettingWindowController(perimeterMeasureInfo: mInfo)
  880. if hideInfoWindow {
  881. self.perimeterMeasureInfoWindowController?.hideFloatingWindow()
  882. }
  883. winC.delegate = self
  884. winC.startModal("")
  885. }
  886. func showMeasureAreaSettingWindow(measureInfo: CPDFAreaMeasureInfo?, hideInfoWindow: Bool = true) {
  887. guard let mInfo = measureInfo else {
  888. return
  889. }
  890. let winC = CAreaSettingWindowController(measureInfo: mInfo)
  891. if hideInfoWindow {
  892. self.areaMeasureInfoWindowController?.hideFloatingWindow()
  893. }
  894. winC.delegate = self
  895. winC.startModal("")
  896. }
  897. // MARK: - 幻灯片
  898. func fadeInFullScreenWindow(with backgroundColor: NSColor, level: Int) {
  899. let view: NSView = self.view.window!.firstResponder as! NSView
  900. if view.isDescendant(of: pdfSplitView){
  901. self.view.window?.makeFirstResponder(nil)
  902. }
  903. self.mainWindow = self.view.window
  904. let fullScreenWindow = KMFullScreenWindow(screen: (self.mainWindow?.screen ?? NSScreen.main)!, bgColor: backgroundColor, level: NSWindow.Level.popUpMenu.rawValue, isMain: true)
  905. fullScreenWindow.interactionParent = self.view.window
  906. self.mainWindow?.delegate = nil
  907. fullScreenWindow.fadeInBlocking()
  908. self.browserWindowController?.window = fullScreenWindow
  909. fullScreenWindow.makeKey()
  910. let sel = NSSelectorFromString("setAnimationBehavior:")
  911. if self.mainWindow?.responds(to: sel) ?? false{
  912. self.mainWindow?.animationBehavior = .none
  913. }
  914. self.mainWindow?.orderOut(nil)
  915. if self.mainWindow?.responds(to: sel) ?? false{
  916. self.mainWindow?.animationBehavior = .default
  917. }
  918. fullScreenWindow.level = NSWindow.Level(rawValue: level)
  919. fullScreenWindow.orderFront(nil)
  920. }
  921. func fadeInFullScreenView(_ view: NSView, inset: CGFloat) {
  922. guard let fullScreenWindow = self.browserWindowController?.window as? KMFullScreenWindow else {
  923. return
  924. }
  925. let fadeWindow = KMFullScreenWindow(screen: fullScreenWindow.screen!, bgColor: fullScreenWindow.backgroundColor, level: fullScreenWindow.level.rawValue, isMain: false)
  926. fadeWindow.order(.above, relativeTo: fullScreenWindow.windowNumber)
  927. view.frame = NSInsetRect(fullScreenWindow.contentView?.bounds ?? .zero, inset, 0)
  928. fullScreenWindow.contentView?.addSubview(view)
  929. self.listView.layoutDocumentView()
  930. self.listView.requiresDisplay()
  931. fullScreenWindow.makeFirstResponder(self.listView)
  932. fullScreenWindow.recalculateKeyViewLoop()
  933. fullScreenWindow.delegate = self.browserWindowController
  934. fullScreenWindow.display()
  935. fadeWindow.fadeOut()
  936. }
  937. // MARK: Redact 【密文标记】
  938. @objc func redact_menuItemClick_delete(sender: NSMenuItem?) {
  939. self.listView.remove(self.listView.activeAnnotation)
  940. }
  941. @objc func redact_menuItemClick_setCurrentPropertyToDefaultValue(sender: NSMenuItem?) {
  942. if (self.listView.activeAnnotation == nil || (self.listView.activeAnnotation.isKind(of: CPDFRedactAnnotation.self)) == false) {
  943. return
  944. }
  945. }
  946. @objc func redact_menuItemClick_apply(sender: NSMenuItem?) {
  947. self.exeRedactConfirm(.redactOne) {}
  948. }
  949. @objc func redact_menuItemClick_clear(sender: NSMenuItem?) {
  950. self.exeRedactConfirm(.eraserOne) {}
  951. }
  952. @objc func redact_menuItemClick_paste(sender: NSMenuItem?) {
  953. }
  954. @objc func exportStampImage(sender:NSMenuItem) {
  955. if listView.activeAnnotation != nil && ((listView.activeAnnotation is CPDFStampAnnotation) || (listView.activeAnnotation is CPDFSignatureAnnotation)) || (self.listView.selectImageAreas != nil) {
  956. var image : NSImage = NSImage()
  957. if (listView.activeAnnotation is CPDFStampAnnotation) {
  958. image = (listView.activeAnnotation as! CPDFStampAnnotation).stampImage()
  959. } else if (listView.activeAnnotation is CPDFSignatureAnnotation) {
  960. image = (listView.activeAnnotation as! CPDFSignatureAnnotation).signImage
  961. } else {
  962. image = self.listView.selectImageAreas.thumbnailImage(with: CGSize(width: 1920, height: 1920)) ?? NSImage()
  963. }
  964. let data = image.tiffRepresentation
  965. if sender.tag == 0 {
  966. let imageRep : NSBitmapImageRep = NSBitmapImageRep(data: data!) ?? NSBitmapImageRep()
  967. imageRep.size = image.size
  968. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.png, properties: [:])!
  969. let savePanel = NSSavePanel()
  970. savePanel.allowedFileTypes = ["png"]
  971. savePanel.beginSheetModal(for: self.view.window!) { response in
  972. if (response != .OK) {
  973. return
  974. }
  975. if NSData(data: imageData).write(to: savePanel.url!, atomically: true) {
  976. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  977. }
  978. }
  979. } else {
  980. let pdfdocument = CPDFDocument()
  981. let signatureImagePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first?.stringByAppendingPathComponent("signatureImage.png")
  982. if NSData(data: data!).write(to: URL(fileURLWithPath: signatureImagePath!), atomically: true) {
  983. pdfdocument?.km_insertPage(image.size, withImage: signatureImagePath!, at: 0)
  984. let savePanel = NSSavePanel()
  985. savePanel.allowedFileTypes = ["pdf"]
  986. savePanel.beginSheetModal(for: self.view.window!) { response in
  987. if (response != .OK) {
  988. return
  989. }
  990. if pdfdocument!.write(to: savePanel.url!) {
  991. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  992. }
  993. }
  994. }
  995. }
  996. }
  997. }
  998. @objc func exportCorpImage(sender:NSMenuItem) {
  999. let rect = NSIntegralRect(listView.currentSelectionRect())
  1000. let orgPage : CPDFPage = listView.currentSelectionPage() ?? listView.currentPage()
  1001. let page : CPDFPage = orgPage.copy() as! CPDFPage
  1002. page.setBounds(rect, for: .cropBox)
  1003. let image = page.thumbnail(of: rect.size) ?? NSImage()
  1004. let data = image.tiffRepresentation
  1005. guard let data = data else { return }
  1006. let imageRep : NSBitmapImageRep = NSBitmapImageRep(data: data) ?? NSBitmapImageRep()
  1007. imageRep.size = rect.size
  1008. let savePanel = NSSavePanel()
  1009. switch sender.tag {
  1010. case 0:
  1011. savePanel.allowedFileTypes = ["png"]
  1012. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.png, properties: [:])!
  1013. savePanel.beginSheetModal(for: self.view.window!) { response in
  1014. if (response != .OK) {
  1015. return
  1016. }
  1017. if NSData(data: imageData).write(to: savePanel.url!, atomically: true) {
  1018. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  1019. }
  1020. }
  1021. case 1:
  1022. savePanel.allowedFileTypes = ["jpg"]
  1023. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
  1024. savePanel.beginSheetModal(for: self.view.window!) { response in
  1025. if (response != .OK) {
  1026. return
  1027. }
  1028. if NSData(data: imageData).write(to: savePanel.url!, atomically: true) {
  1029. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  1030. }
  1031. }
  1032. case 2:
  1033. savePanel.allowedFileTypes = ["pdf"]
  1034. let pdfdocument = CPDFDocument()
  1035. let signatureImagePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first?.stringByAppendingPathComponent("signatureImage.png")
  1036. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
  1037. if NSData(data: imageData).write(to: URL(fileURLWithPath: signatureImagePath!), atomically: true) {
  1038. pdfdocument?.insertPage(image.size, withImage: signatureImagePath, at: 0)
  1039. savePanel.beginSheetModal(for: self.view.window!) { response in
  1040. if (response != .OK) {
  1041. return
  1042. }
  1043. if pdfdocument!.write(to: savePanel.url!) {
  1044. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  1045. }
  1046. }
  1047. }
  1048. default:
  1049. break
  1050. }
  1051. // 执行右键操作后,需要取消框选区域
  1052. if self.listView.toolMode == .CSelectToolMode {
  1053. objc_sync_enter(self)
  1054. self.listView.selectionRect = NSZeroRect
  1055. self.listView.selectionPageIndex = UInt(NSNotFound)
  1056. objc_sync_exit(self)
  1057. }
  1058. }
  1059. @IBAction func doZoomToAutoSelection(sender:NSMenuItem) {
  1060. let rect = listView.currentSelectionRect()
  1061. let page = listView.currentPage()
  1062. if NSIsEmptyRect(rect) == false && page != nil {
  1063. let isLegacy = NSScroller.responds(to: NSSelectorFromString("preferredScrollerStyle")) == false || NSScroller.preferredScrollerStyle == .legacy
  1064. var bounds = listView.bounds
  1065. var scale = 1.0
  1066. if isLegacy {
  1067. bounds.size.width -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle)
  1068. bounds.size.height -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle)
  1069. }
  1070. if NSWidth(bounds) * NSHeight(rect) > NSWidth(rect) * NSHeight(bounds) {
  1071. scale = NSHeight(bounds) / NSHeight(rect)
  1072. } else {
  1073. scale = NSWidth(bounds) / NSWidth(rect)
  1074. }
  1075. listView.setScaleFactor(scale, animated: false)
  1076. let scrollView = listView.scroll()
  1077. if isLegacy && scrollView?.hasHorizontalScroller == false || scrollView?.hasVerticalScroller == false {
  1078. if ((scrollView?.hasVerticalScroller) != nil) {
  1079. bounds.size.width -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle)
  1080. }
  1081. if ((scrollView?.hasHorizontalScroller) != nil) {
  1082. bounds.size.height -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle)
  1083. }
  1084. if NSWidth(bounds) * NSHeight(rect) > NSWidth(rect) * NSHeight(bounds) {
  1085. scale = NSHeight(bounds) / NSHeight(rect)
  1086. } else {
  1087. scale = NSWidth(bounds) / NSWidth(rect)
  1088. }
  1089. listView.setScaleFactor(scale, animated: false)
  1090. }
  1091. DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) { [self] in
  1092. let pagePoint = CGPoint(x: rect.origin.x, y: (rect.origin.y + rect.size.height))
  1093. listView.go(toTargetPoint: pagePoint, on: page, at: .top)
  1094. };
  1095. }
  1096. // 执行右键操作后,需要取消框选区域
  1097. if self.listView.toolMode == .CSelectToolMode {
  1098. objc_sync_enter(self)
  1099. self.listView.selectionRect = NSZeroRect
  1100. self.listView.selectionPageIndex = UInt(NSNotFound)
  1101. objc_sync_exit(self)
  1102. }
  1103. }
  1104. private func cropPagesToRects(rects:NSPointerArray) {
  1105. }
  1106. //MARK: - action
  1107. // 开启/关闭左边栏
  1108. @objc func toggleLeftPane() -> Void {
  1109. self.model.leftPanelOpen = true
  1110. applyLeftSideWidth(self.model.panelWidth+functionWidth, rightSideWidth: self.model.lastRightPanWidth)
  1111. }
  1112. // 开启左边栏
  1113. @objc func openLeftPane() -> Void {
  1114. self.model.leftPanelOpen = true
  1115. applyLeftSideWidth(self.model.panelWidth+functionWidth, rightSideWidth: self.model.lastRightPanWidth)
  1116. }
  1117. // 关闭左边栏
  1118. @objc func closeLeftPane() -> Void {
  1119. self.model.leftPanelOpen = false
  1120. applyLeftSideWidth(functionWidth, rightSideWidth: self.model.lastRightPanWidth)
  1121. }
  1122. func rename(_ sender: NSNotification) -> Void {
  1123. if (self.view.window == nil || self.view.window!.isVisible == false) {
  1124. return
  1125. }
  1126. let tabController = sender.object as? CTTabController
  1127. if tabController?.title == self.document?.documentURL.deletingPathExtension().lastPathComponent {
  1128. if let doc = self.myDocument, doc.isDocumentEdited {
  1129. Task {
  1130. let resp = await KMAlertTool.runModel(message: NSLocalizedString("File Updated", comment: ""), buttons: [NSLocalizedString("Save", comment: ""), NSLocalizedString("Cancel", comment: "")])
  1131. if resp != .alertFirstButtonReturn { // 取消
  1132. return
  1133. }
  1134. doc.updateChangeCount(.changeCleared)
  1135. self.document?.write(to: doc.fileURL)
  1136. Task { @MainActor in
  1137. self._renameForSavePanel(tabController)
  1138. }
  1139. }
  1140. return
  1141. }
  1142. self._renameForSavePanel(tabController)
  1143. }
  1144. }
  1145. func savePdfAlertView() {
  1146. if AutoSaveManager.manager.isSaving || AutoSaveManager.manager.isSaveNoti{
  1147. return
  1148. }
  1149. AutoSaveManager.manager.isSaveNoti = true
  1150. var num = 0
  1151. if self.listView.document != nil{
  1152. num = Int(self.listView.document.pageCount)
  1153. }
  1154. if Thread.current.isMainThread {
  1155. self.beginProgressSheet(withMessage: NSLocalizedString("Saving PDF", comment: "") + "...", maxValue: UInt(num))
  1156. } else {
  1157. DispatchQueue.main.async {
  1158. self.beginProgressSheet(withMessage: NSLocalizedString("Saving PDF", comment: "") + "...", maxValue: UInt(num))
  1159. }
  1160. }
  1161. }
  1162. func savePdfFinishAlertView() {
  1163. if !AutoSaveManager.manager.isSaveNoti{
  1164. return
  1165. }
  1166. AutoSaveManager.manager.isSaveNoti = false
  1167. if Thread.current.isMainThread {
  1168. self.dismissProgressSheet()
  1169. } else {
  1170. DispatchQueue.main.async {
  1171. self.dismissProgressSheet()
  1172. }
  1173. }
  1174. }
  1175. private func _renameForSavePanel(_ tabC: CTTabController?) {
  1176. let outputSavePanel = NSSavePanel()
  1177. outputSavePanel.title = NSLocalizedString("Rename", comment: "")
  1178. outputSavePanel.allowedFileTypes = ["pdf"]
  1179. outputSavePanel.nameFieldStringValue = (self.document?.documentURL.lastPathComponent)!
  1180. outputSavePanel.directoryURL = self.document?.documentURL.deletingLastPathComponent()
  1181. let resp = outputSavePanel.runModal()
  1182. if resp == .OK {
  1183. let pdfDocument = CPDFDocument(url: self.document?.documentURL)
  1184. let fileURL = pdfDocument?.documentURL
  1185. let fileManager = FileManager.default
  1186. let newFileURL = fileURL!.deletingLastPathComponent().appendingPathComponent(outputSavePanel.url!.lastPathComponent)
  1187. var result = true
  1188. do {
  1189. try fileManager.moveItem(at: fileURL!, to: newFileURL)
  1190. } catch {
  1191. result = false
  1192. KMPrint("Error renaming file! Threw: \(error.localizedDescription)")
  1193. }
  1194. if (result) {
  1195. tabC?.title = outputSavePanel.url!.lastPathComponent
  1196. if let newPdfDocument = CPDFDocument(url: newFileURL) {
  1197. self.model.isSaveKeyChain = false
  1198. newPdfDocument.unlock(withPassword: self.document?.password)
  1199. if (newPdfDocument.pageCount > 0) {
  1200. self.setDocument = newPdfDocument
  1201. }
  1202. }
  1203. }
  1204. } else {
  1205. outputSavePanel.close()
  1206. }
  1207. }
  1208. func showInFinder(_ sender: Any) -> Void {
  1209. if sender is NSNotification {
  1210. let tabController = (sender as! NSNotification).object as? CTTabController
  1211. let path = self.document?.documentURL.deletingPathExtension().lastPathComponent
  1212. if tabController?.title == path {
  1213. if let file = self.myDocument?.fileURL {
  1214. if FileManager.default.fileExists(atPath: file.path) {
  1215. NSWorkspace.shared.activateFileViewerSelecting([file])
  1216. }
  1217. }
  1218. }
  1219. } else {
  1220. guard let url = self.myDocument?.fileURL else { return }
  1221. let file: URL = url
  1222. if FileManager.default.fileExists(atPath: file.path) {
  1223. NSWorkspace.shared.activateFileViewerSelecting([file])
  1224. }
  1225. }
  1226. }
  1227. func closeTab(_ sender: NSNotification) -> Void {
  1228. }
  1229. @IBAction func toggleSplitPDF(_ sender: Any) {
  1230. }
  1231. internal func showConvertWindow(type: KMToolbarType, documentUrl: URL? = nil, identifier: String?) {
  1232. if let wc = self.currentWindowController as? KMConvertBaseWindowController, let _ = wc.window?.isSheet {
  1233. KMPrint("转档窗口已显示")
  1234. return
  1235. }
  1236. var convertT: KMConvertType = .Word
  1237. var windowController: KMConvertBaseWindowController?
  1238. if (type == .word) { /// Word
  1239. convertT = .Word
  1240. windowController = KMConvertWordWindowController()
  1241. } else if (type == .excel) {
  1242. convertT = .Excel
  1243. } else if (type == .ppt || type == .rtf || type == .html || type == .conversion_text) {
  1244. if (type == .ppt) {
  1245. convertT = .PPT
  1246. } else if (type == .rtf) {
  1247. convertT = .RTF
  1248. } else if (type == .html) {
  1249. convertT = .HTML
  1250. } else if (type == .conversion_text) {
  1251. convertT = .Text
  1252. }
  1253. } else if (type == .csv) {
  1254. convertT = .CSV
  1255. } else if (type == .conversion_image) {
  1256. windowController = KMConvertImageWindowController()
  1257. convertT = .JPEG
  1258. } else if type == .json {
  1259. convertT = .Json
  1260. }
  1261. var url: URL?
  1262. if (documentUrl != nil) {
  1263. url = documentUrl
  1264. windowController?.oriDocumentUrl = self.listView.document.documentURL
  1265. } else {
  1266. url = self.listView.document.documentURL
  1267. }
  1268. let model = KMDocumentModel(url: url!)
  1269. windowController?.documentModel = model
  1270. self.km_safe_beginSheet(windowC: windowController)
  1271. }
  1272. //MARK: 转档 -
  1273. func showAllConvertWindow(convertT: KMConvertType) {
  1274. let convertWC = KMConvertWindowController(documemtV: self.document!, currentPage: self.listView.currentPage(), convertT: convertT) {
  1275. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) { [self] in
  1276. var type: KMConvertWithPDFType = .WordAdvance
  1277. switch convertT {
  1278. case .Word:
  1279. break
  1280. case .Excel:
  1281. type = .Excel
  1282. case .PPT:
  1283. type = .PowerPoint
  1284. case .RTF:
  1285. type = .RTF
  1286. case .CSV:
  1287. type = .CSV
  1288. case .HTML:
  1289. type = .HTML
  1290. case .Text:
  1291. type = .Text
  1292. case .JPEG:
  1293. type = .JPEG
  1294. case .PNG:
  1295. type = .PNG
  1296. case .GIF:
  1297. type = .GIF
  1298. case .JPG:
  1299. type = .JPG
  1300. case .TIFF:
  1301. type = .TIFF
  1302. case .TGA:
  1303. type = .TGA
  1304. case .BMP:
  1305. type = .BMP
  1306. case .JP2:
  1307. type = .JPEG2000
  1308. case .AdvancedWord:
  1309. break
  1310. case .Json:
  1311. type = .Json
  1312. break
  1313. default:
  1314. break
  1315. }
  1316. let batchWindowController = KMBatchOperateWindowController.sharedWindowController
  1317. var needShowHint = false
  1318. if KMConvertOperationQueue.sharedQueue.operations.count > 0 {
  1319. needShowHint = true
  1320. } else {
  1321. var needContinue = false
  1322. if KMBatchOperateManager.defaultManager.files?.count ?? 0 > 0 {
  1323. let arr: [String] = converFilesToPath(files: KMBatchOperateManager.defaultManager.files!)
  1324. let ss = self.document?.documentURL.path
  1325. if arr.contains(ss!) {
  1326. needContinue = false
  1327. }else {
  1328. needContinue = true
  1329. }
  1330. }else {
  1331. needContinue = true
  1332. }
  1333. if needContinue {
  1334. let ss = self.document?.documentURL.path
  1335. let file = KMBatchOperateFile(filePath: ss!, type: .Convert)
  1336. file.password = document?.password ?? ""
  1337. KMBatchOperateManager.defaultManager.files?.append(file)
  1338. }
  1339. batchWindowController.switchToOperateType(.Convert, files: KMBatchOperateManager.defaultManager.files!)
  1340. batchWindowController.switchToConvertType(convertType: type)
  1341. }
  1342. batchWindowController.window?.makeKeyAndOrderFront(nil)
  1343. if needShowHint {
  1344. batchWindowController.showIsConvertingHint()
  1345. } else {
  1346. }
  1347. }
  1348. }
  1349. self.km_beginSheet(windowC: convertWC)
  1350. }
  1351. //MARK: 转档 - OCR
  1352. // func showOCRWindow() {
  1353. // if !IAPProductsManager.default().isAvailableAllFunction(){
  1354. // let winC = KMPurchaseCompareWindowController.sharedInstance()
  1355. // winC?.showWindow(nil)
  1356. // return
  1357. // }
  1358. // let com = KMOCRPDFWindowController(cpdfDocument: self.listView.document!, pwd: self.listView.document?.password ?? "")
  1359. // com.currentIndexPage = self.listView.currentPageIndex
  1360. // self.km_beginSheet(windowC: com)
  1361. // }
  1362. // MARK: - 图片注释
  1363. @IBAction func imageAnnotation(_ sender: Any) {
  1364. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Tools_Image"])
  1365. changeAnnotationMode(sender)
  1366. guard IAPProductsManager.default().isAvailableAllFunction() else {
  1367. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  1368. return
  1369. }
  1370. let accessoryCtr = KMImageAccessoryController()
  1371. let openPanel = NSOpenPanel()
  1372. openPanel.allowedFileTypes = KMImageAccessoryController.supportedImageTypes()
  1373. openPanel.allowsMultipleSelection = false
  1374. openPanel.accessoryView = accessoryCtr.view
  1375. openPanel.canSelectHiddenExtension = true
  1376. openPanel.beginSheetModal(for: NSApp.mainWindow!) { [self] (result) in
  1377. if result == .OK {
  1378. guard let url = openPanel.url else {
  1379. return
  1380. }
  1381. let filePath = url.path
  1382. if filePath.pathExtension.lowercased() == "pdf" {
  1383. if let pdf = PDFDocument(url: url), pdf.isEncrypted {
  1384. NSSound.beep()
  1385. return
  1386. }
  1387. }
  1388. guard let image = NSImage(contentsOfFile: url.path) else {
  1389. let alert = NSAlert()
  1390. alert.alertStyle = .critical
  1391. alert.messageText = String(format: NSLocalizedString("The file \"%@\" could not be opened.", comment: ""), url.lastPathComponent)
  1392. alert.informativeText = NSLocalizedString("It may be damaged or use a file format that PDF Reader Pro doesn’t recognize.", comment: "")
  1393. alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
  1394. alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
  1395. if response == .alertFirstButtonReturn {
  1396. // Handle cancel button clicked
  1397. }
  1398. }
  1399. return
  1400. }
  1401. let isDamageImage: Bool = self.isDamageImage(image, imagePath: url.path)
  1402. if isDamageImage {
  1403. let alert = NSAlert()
  1404. alert.alertStyle = .critical
  1405. alert.messageText = String(format: NSLocalizedString("The file \"%@\" could not be opened.", comment: ""), url.lastPathComponent)
  1406. alert.informativeText = NSLocalizedString("It may be damaged or use a file format that PDF Reader Pro doesn’t recognize.", comment: "")
  1407. alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
  1408. alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
  1409. if response == .alertFirstButtonReturn {
  1410. // Handle cancel button clicked
  1411. }
  1412. }
  1413. return
  1414. }
  1415. let isRemoveBGColor = accessoryCtr.selectedButton.state == .on
  1416. listView.addAnnotation(with: image, isRemoveBGColor: isRemoveBGColor)
  1417. if (self.listView.activeAnnotation != nil) && (self.listView.activeAnnotation.type == "Image") {
  1418. }
  1419. }
  1420. }
  1421. }
  1422. @IBAction func tableAnnotation(_ sender: Any) {
  1423. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Tools_Table"])
  1424. changeAnnotationMode(sender)
  1425. guard IAPProductsManager.default().isAvailableAllFunction() else {
  1426. let winC = KMPurchaseCompareWindowController.sharedInstance()
  1427. winC?.kEventName = "Reading_Table_BuyNow"
  1428. winC?.showWindow(nil)
  1429. return
  1430. }
  1431. listView.addAnnotationWithTable()
  1432. toggleOpenRightSide()
  1433. }
  1434. func isDamageImage(_ image: NSImage, imagePath path: String) -> Bool {
  1435. let addImageAnnotation = (NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last! as NSString).appendingPathComponent(Bundle.main.bundleIdentifier!)
  1436. if !FileManager.default.fileExists(atPath: addImageAnnotation) {
  1437. try? FileManager.default.createDirectory(atPath: addImageAnnotation, withIntermediateDirectories: false, attributes: nil)
  1438. }
  1439. if let data = image.tiffRepresentation,
  1440. let imageRep = NSBitmapImageRep(data: data) {
  1441. imageRep.size = image.size
  1442. var imageData: Data?
  1443. if path.lowercased() == "png" {
  1444. imageData = imageRep.representation(using: .png, properties: [:])
  1445. } else {
  1446. imageData = imageRep.representation(using: .jpeg, properties: [:])
  1447. }
  1448. if let imageData = imageData {
  1449. let rPath = (addImageAnnotation as NSString).appendingPathComponent((self.tagString() as NSString).appendingPathExtension("png")!)
  1450. if !((try? imageData.write(to: URL(fileURLWithPath: rPath), options: .atomicWrite)) != nil) {
  1451. return true
  1452. } else {
  1453. return false
  1454. }
  1455. }
  1456. }
  1457. return false
  1458. }
  1459. func tagString() -> String {
  1460. let dateFormatter = DateFormatter()
  1461. dateFormatter.dateFormat = "yyMMddHHmmss"
  1462. return "\(dateFormatter.string(from: Date()))\(Int.random(in: 0..<10000))"
  1463. }
  1464. func updateBackAndForwardButtonState() {
  1465. }
  1466. }
  1467. extension KMMainViewController {
  1468. func changeModelAction(mode: CToolMode) {
  1469. self.listView.toolMode = mode
  1470. if mode == .CEditPDFToolMode {
  1471. }
  1472. }
  1473. func changePDFViewZoomInAction() {
  1474. }
  1475. func changePDFViewZoomOutAction() {
  1476. }
  1477. func changePDFViewGotoNextPageAction() {
  1478. self.listView.km_goBack(nil)
  1479. if (self.listView.canGoToNextPage()) {
  1480. self.listView.goToNextPage(nil)
  1481. }
  1482. }
  1483. func changePDFViewGoToPreviousPageAction() {
  1484. if (self.listView.canGoToPreviousPage()) {
  1485. self.listView.goToPreviousPage(nil)
  1486. }
  1487. }
  1488. func changePDFViewGotoBackAction() {
  1489. self.listView.km_goBack(nil)
  1490. self.updateBackAndForwardButtonState()
  1491. }
  1492. func changePDFViewGoToForwardAction() {
  1493. self.listView.km_goForward(nil)
  1494. self.updateBackAndForwardButtonState()
  1495. }
  1496. func aiTranslationPDFFileAction() {
  1497. self.trackEvent_aiTranslate()
  1498. self._aiTranslationPDFFileAction()
  1499. }
  1500. private func _aiTranslationPDFFileAction() {
  1501. let isExceedsLimit = self.isPDFPageCountExceedsLimit(filePath: (self.document?.documentURL.path)!)
  1502. if KMTools.isFileGreaterThan10MB(atPath: (self.document?.documentURL.path)!) {
  1503. let alert = NSAlert()
  1504. alert.alertStyle = .critical
  1505. alert.messageText = NSLocalizedString("The uploaded file size cannot exceed 10MB", comment: "")
  1506. alert.runModal()
  1507. return
  1508. } else if isExceedsLimit {
  1509. let alert = NSAlert()
  1510. alert.alertStyle = .critical
  1511. alert.messageText = NSLocalizedString("Documents cannot exceed 30 pages", comment: "")
  1512. alert.runModal()
  1513. return
  1514. }
  1515. let alert = NSAlert()
  1516. alert.messageText = NSLocalizedString("Processing times may be longer for larger documents. Thank you for your patience.", comment: "")
  1517. alert.addButton(withTitle: NSLocalizedString("Continue", comment: ""))
  1518. alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
  1519. alert.beginSheetModal(for: view.window!) { [weak self] result in
  1520. if (result == .alertFirstButtonReturn) {
  1521. } else if result == .alertSecondButtonReturn {
  1522. return
  1523. }
  1524. }
  1525. }
  1526. func showBatchWindow(type: KMBatchOperationType, filepaths: [String]?) {
  1527. let batchWindowController = KMBatchOperateWindowController.sharedWindowController
  1528. var array: [KMBatchOperateFile] = []
  1529. for fpath in filepaths ?? [] {
  1530. let batchOperateFile = KMBatchOperateFile(filePath: fpath, type: type)
  1531. array.append(batchOperateFile)
  1532. }
  1533. batchWindowController.switchToOperateType(type, files: array)
  1534. batchWindowController.window?.makeKeyAndOrderFront("")
  1535. }
  1536. func openNewWindowAlertWindow() {
  1537. var needShowChooseWindow = false
  1538. //#if VERSION_FREE
  1539. if (!IAPProductsManager.default().isAvailableAllFunction()) {
  1540. needShowChooseWindow = true
  1541. }
  1542. //#endif
  1543. if needShowChooseWindow {
  1544. let preferenceNoteShow = UserDefaults.standard.bool(forKey: KMTabbingHintShowFlag)
  1545. if preferenceNoteShow {
  1546. menuItemAction_newTagPageToNewWindow("")
  1547. } else {
  1548. if !KMDataManager.default.isTabbingWin{
  1549. KMDataManager.default.isTabbingWin = true
  1550. let tabbingWin: KMTabbingHintWindowController = KMTabbingHintWindowController()
  1551. tabbingWin.selectCallBack = {[weak self] continueOrNot in
  1552. KMDataManager.default.isTabbingWin = false
  1553. if continueOrNot {
  1554. self?.reopenDocument(forPaths: [])
  1555. } else {
  1556. }
  1557. }
  1558. self.km_beginSheet(windowC: tabbingWin)
  1559. }
  1560. }
  1561. }else{
  1562. handleTabbingLogic()
  1563. }
  1564. }
  1565. func reopenDocument(forPaths paths: [String]) -> Void {
  1566. let browser = KMBrowser.init() as KMBrowser
  1567. browser.windowController = KMBrowserWindowController.init(browser: browser)
  1568. browser.addHomeTabContents()
  1569. browser.windowController.showWindow(self)
  1570. }
  1571. func handleTabbingLogic() {
  1572. self.browserWindowController?.browser?.selectTabContents(at: 0, userGesture: true)
  1573. }
  1574. func convertToImg(index: Int) {
  1575. var convertT: KMConvertType = .JPEG
  1576. switch index {
  1577. case 7:
  1578. convertT = .JPEG
  1579. case 8:
  1580. convertT = .JPG
  1581. case 9:
  1582. convertT = .PNG
  1583. case 10:
  1584. convertT = .GIF
  1585. case 11:
  1586. convertT = .TIFF
  1587. case 12:
  1588. convertT = .TGA
  1589. case 13:
  1590. convertT = .BMP
  1591. default:
  1592. convertT = .JPEG
  1593. }
  1594. showAllConvertWindow(convertT: convertT)
  1595. }
  1596. }
  1597. // MARK: CDistanceMeasureInfoWindowControllerDelegate
  1598. extension KMMainViewController : CDistanceMeasureInfoWindowControllerDelegate {
  1599. func distanceMeasureInfoWindowControllerSetting(_ distanceMeasureInfoWindowController: CDistanceMeasureInfoWindowController) {
  1600. let distanceSettingWC = CDistanceSettingWindowController(distanceMeasureInfo: self.distanceMeasureInfoWindowController!.measureInfo)
  1601. self.distanceMeasureInfoWindowController?.hideFloatingWindow()
  1602. distanceSettingWC.delegate = self
  1603. distanceSettingWC.startModal("")
  1604. }
  1605. func cancelMeasureInfoWindowControllerSetting(_ distanceMeasureInfoWindowController: CDistanceMeasureInfoWindowController) {
  1606. }
  1607. }
  1608. // MARK: CPerimeterMeasureInfoWindowControllerDelegate
  1609. extension KMMainViewController : CPerimeterMeasureInfoWindowControllerDelegate {
  1610. func perimeterMeasureInfoWindowControllerSetting(_ perimeterMeasureInfoWindowController: CPerimeterMeasureInfoWindowController) {
  1611. let distanceSettingWC = CDistanceSettingWindowController(perimeterMeasureInfo: self.perimeterMeasureInfoWindowController!.measureInfo)
  1612. self.distanceMeasureInfoWindowController?.hideFloatingWindow()
  1613. distanceSettingWC.delegate = self
  1614. distanceSettingWC.startModal("")
  1615. }
  1616. }
  1617. // MARK: CAreaMeasureInfoWindowControllerDelegate
  1618. extension KMMainViewController : CAreaMeasureInfoWindowControllerDelegate {
  1619. func areaMeasureInfoWindowControllerSetting(_ areaMeasureInfoWindowController: CAreaMeasureInfoWindowController) {
  1620. let areaSettingWC = CAreaSettingWindowController(measureInfo: self.areaMeasureInfoWindowController!.measureInfo)
  1621. self.areaMeasureInfoWindowController?.hideFloatingWindow()
  1622. areaSettingWC.delegate = self
  1623. areaSettingWC.startModal("")
  1624. }
  1625. }
  1626. // MARK: CDistanceSettingWindowControllerDelegate
  1627. extension KMMainViewController : CDistanceSettingWindowControllerDelegate {
  1628. func distanceSettingWindowController(_ distanceSettingWindowController: CDistanceSettingWindowController, distanceMeasureInfo: CPDFDistanceMeasureInfo?) {
  1629. if distanceMeasureInfo != nil {
  1630. if self.listView.activeAnnotations.count > 0 {
  1631. if self.listView.activeAnnotation.isKind(of: CPDFLineAnnotation.self) {
  1632. (self.listView.activeAnnotation as! CPDFLineAnnotation).measureInfo = distanceMeasureInfo
  1633. self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page)
  1634. }
  1635. self.distanceMeasureInfoWindowController?.reloadData(with: (self.listView.activeAnnotation as! CPDFLineAnnotation).measureInfo!)
  1636. } else {
  1637. distanceMeasureInfo?.leadLength = 0
  1638. self.listView.distanceMeasureInfo = distanceMeasureInfo
  1639. self.distanceMeasureInfoWindowController?.reloadData(with: self.listView.distanceMeasureInfo)
  1640. self.distanceMeasureInfoWindowController?.lengthLabel.stringValue = ""
  1641. self.distanceMeasureInfoWindowController?.angleLabel.stringValue = ""
  1642. self.distanceMeasureInfoWindowController?.xLabel.stringValue = ""
  1643. self.distanceMeasureInfoWindowController?.yLabel.stringValue = ""
  1644. }
  1645. if let data = self.listView.activeAnnotation {
  1646. }
  1647. }
  1648. self.distanceMeasureInfoWindowController?.showWindow(self)
  1649. }
  1650. func distanceSettingWindowController(_ distanceSettingWindowController: CDistanceSettingWindowController, perimeterMeasureInfo: CPDFPerimeterMeasureInfo?) {
  1651. if perimeterMeasureInfo != nil {
  1652. if self.listView.activeAnnotations.count > 0 {
  1653. if self.listView.activeAnnotation.isKind(of: CPDFPolylineAnnotation.self) {
  1654. (self.listView.activeAnnotation as! CPDFPolylineAnnotation).measureInfo = perimeterMeasureInfo
  1655. self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page)
  1656. }
  1657. self.perimeterMeasureInfoWindowController?.reloadData(with: (self.listView.activeAnnotation as! CPDFPolylineAnnotation).measureInfo!)
  1658. } else {
  1659. self.listView.perimeterMeasureInfo = perimeterMeasureInfo
  1660. self.perimeterMeasureInfoWindowController?.reloadData(with: self.listView.perimeterMeasureInfo)
  1661. self.perimeterMeasureInfoWindowController?.lengthLabel.stringValue = ""
  1662. self.perimeterMeasureInfoWindowController?.angleLabel.stringValue = ""
  1663. }
  1664. if let data = self.listView.activeAnnotation {
  1665. }
  1666. }
  1667. self.perimeterMeasureInfoWindowController?.showWindow(self)
  1668. }
  1669. }
  1670. // MARK: CAreaSettingWindowControllerDelegate
  1671. extension KMMainViewController : CAreaSettingWindowControllerDelegate {
  1672. func areaSettingWindowController(_ areaSettingWindowController: CAreaSettingWindowController, measureInfo: CPDFAreaMeasureInfo?) {
  1673. if self.listView.annotationType == .measureSquare && self.listView.toolMode == .CNoteToolMode {
  1674. if measureInfo != nil {
  1675. if self.listView.activeAnnotations.count > 0 {
  1676. if self.listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) {
  1677. (self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo = measureInfo
  1678. self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page)
  1679. }
  1680. self.areaMeasureInfoWindowController?.reloadData((self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo!)
  1681. } else {
  1682. self.listView.squareAreaMeasureInfo = measureInfo
  1683. self.areaMeasureInfoWindowController?.reloadData(self.listView.squareAreaMeasureInfo)
  1684. self.areaMeasureInfoWindowController?.areaLabel.stringValue = ""
  1685. self.areaMeasureInfoWindowController?.angleLabel.stringValue = ""
  1686. }
  1687. }
  1688. self.areaMeasureInfoWindowController?.showWindow(self)
  1689. } else if self.listView.annotationType == .measurePolyGon && self.listView.toolMode == .CNoteToolMode {
  1690. if measureInfo != nil {
  1691. if self.listView.activeAnnotations.count > 0 {
  1692. if self.listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) {
  1693. (self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo = measureInfo
  1694. self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page)
  1695. }
  1696. self.areaMeasureInfoWindowController?.reloadData((self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo!)
  1697. } else {
  1698. self.listView.polygonAreaMeasureInfo = measureInfo
  1699. self.areaMeasureInfoWindowController?.reloadData(self.listView.polygonAreaMeasureInfo)
  1700. self.areaMeasureInfoWindowController?.areaLabel.stringValue = ""
  1701. self.areaMeasureInfoWindowController?.angleLabel.stringValue = ""
  1702. }
  1703. }
  1704. self.areaMeasureInfoWindowController?.showWindow(self)
  1705. } else {
  1706. if measureInfo != nil {
  1707. if self.listView.activeAnnotations.count > 0 {
  1708. if self.listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) {
  1709. (self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo = measureInfo
  1710. self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page)
  1711. }
  1712. self.areaMeasureInfoWindowController?.reloadData((self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo!)
  1713. }
  1714. }
  1715. self.areaMeasureInfoWindowController?.showWindow(self)
  1716. }
  1717. if measureInfo != nil {
  1718. if let data = self.listView.activeAnnotation {
  1719. }
  1720. }
  1721. }
  1722. }
  1723. //MARK: LeftSideViewController
  1724. extension KMMainViewController {
  1725. func leftSideViewCancelSelect() {
  1726. if self.listView.isEditing() == true {
  1727. if self.listView.editingAreas() != nil &&
  1728. self.listView.editingAreas().count != 0 {
  1729. let areas = self.listView.editingAreas().first
  1730. if areas is CPDFEditTextArea {
  1731. self.listView.clearEditingSelectCharItem()
  1732. self.listView.updateEditing([])
  1733. KMPrint("取消选中")
  1734. }
  1735. }
  1736. }
  1737. }
  1738. }
  1739. // MARK: - Analytics (埋点)
  1740. extension KMMainViewController {
  1741. func trackEvent(toolType type: KMToolbarViewType) -> Void {
  1742. if (type == .Annatiton) {
  1743. FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn" : "Btn_Tbr_Tools"])
  1744. } else if (type == .editPDF) {
  1745. } else if (type == .Page) {
  1746. FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn" : "Btn_Tbr_PageEdit"])
  1747. } else if (type == .Conversion) {
  1748. } else if (type == .Tool) {
  1749. }
  1750. }
  1751. func trackEvent_aiTranslate() -> Void {
  1752. KMAnalytics.trackEvent(eventName: "Btn_Tbr_AITranslate", parameters: [
  1753. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr,
  1754. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all)
  1755. }
  1756. func trackEvent_print() -> Void {
  1757. KMAnalytics.trackEvent(eventName: "Btn_Tbr_Print", parameters: [
  1758. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr,
  1759. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all)
  1760. }
  1761. func trackEvent_share() -> Void {
  1762. KMAnalytics.trackEvent(eventName: "Btn_Tbr_Share", parameters: [
  1763. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr,
  1764. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all)
  1765. }
  1766. func trackEvent_upgrade() -> Void {
  1767. KMAnalytics.trackEvent(eventName: "Btn_Tbr_Upgrade", parameters: [
  1768. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr,
  1769. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all)
  1770. }
  1771. func trackEvent(annotationType type: CAnnotationType) -> Void {
  1772. if (type == .highlight) {
  1773. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Highlight"])
  1774. } else if (type == .underline) {
  1775. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Underline"])
  1776. } else if (type == .strikeOut) {
  1777. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Strikethrough"])
  1778. } else if (type == .ink) {
  1779. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Freehand"])
  1780. } else if (type == .freeText) {
  1781. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_TextBox"])
  1782. } else if (type == .anchored) {
  1783. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_AnchoredNote"])
  1784. } else if (type == .square) {
  1785. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Rectangle"])
  1786. } else if (type == .link) {
  1787. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Link"])
  1788. } else if (type == .stamp) {
  1789. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Stamp"])
  1790. } else if (type == .signSignature) {
  1791. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Signature"])
  1792. } else if (type == .circle) {
  1793. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Oval"])
  1794. } else if (type == .arrow) {
  1795. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Arrow"])
  1796. } else if (type == .line) {
  1797. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Line"])
  1798. } else if (self.listView.isEditing() && self.listView.shouAddEditAreaType() == .text) {
  1799. KMAnalytics.trackEvent(eventName: "Btn_SubTbr_AddText", parameters: [
  1800. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_editPDF,
  1801. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all)
  1802. } else if (self.listView.isEditing() && self.listView.shouAddEditAreaType() == .image) {
  1803. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Image"])
  1804. } else if (type == .textField) {
  1805. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_TextField"])
  1806. } else if (type == .checkBox) {
  1807. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_CheckBox"])
  1808. } else if (type == .radioButton) {
  1809. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_RadioButton"])
  1810. } else if (type == .listMenu) {
  1811. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_ListBox"])
  1812. } else if (type == .comboBox) {
  1813. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_ComboBox"])
  1814. } else if (type == .actionButton) {
  1815. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_Button"])
  1816. } else if (type == .actionButton) {
  1817. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_Button"])
  1818. } else if (type == .signature) {
  1819. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_Signature"])
  1820. } else if (type == .squiggly) {
  1821. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Squiglly"])
  1822. } else if (type == .eraser) {
  1823. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Erasder"])
  1824. }
  1825. }
  1826. func trackEvent(toolMode mode: CToolMode) -> Void {
  1827. if (mode == .CSelectToolMode) {
  1828. KMAnalytics.trackEvent(eventName: "Btn_SubTbr_ContentSelection", parameters: [
  1829. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation,
  1830. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all)
  1831. } else if (mode == .CMoveToolMode) {
  1832. KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Scroll", parameters: [
  1833. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation,
  1834. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all)
  1835. } else if mode == .CNoteToolMode {
  1836. if CPDFListView.isMeasure(self.listView.annotationType) == true {
  1837. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Editor_Measure"])
  1838. }
  1839. }
  1840. }
  1841. func trackEvent(toolBarType type: KMToolbarType) -> Void {
  1842. if (type == .word) {
  1843. } else if (type == .excel) {
  1844. } else if (type == .ppt) {
  1845. } else if (type == .rtf) {
  1846. } else if (type == .csv) {
  1847. } else if (type == .html) {
  1848. } else if (type == .conversion_text) {
  1849. } else if (type == .conversion_image) {
  1850. } else if (type == .compress) {
  1851. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Compress"])
  1852. } else if (type == .merge) {
  1853. } else if (type == .secure) {
  1854. } else if (type == .crop) {
  1855. } else if type == .json {
  1856. FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Converter", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Converter_ToOthers_ToJson"])
  1857. }
  1858. }
  1859. func trackEvent_setPassword() -> Void {
  1860. KMAnalytics.trackEvent(eventName: "Btn_SubTbr_SetPassword", parameters: [
  1861. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_Tools,
  1862. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all)
  1863. }
  1864. func trackEvent_removePassword() -> Void {
  1865. KMAnalytics.trackEvent(eventName: "Btn_SubTbr_RemovePassword", parameters: [
  1866. KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_Tools,
  1867. KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all)
  1868. }
  1869. func trackEvent_replace() -> Void {
  1870. self.trackEvent(eventName: "Tbr", params: ["Tbr_Btn" : "Btn_Tbr_ReplaceText"], platform: .AppCenter)
  1871. }
  1872. }
  1873. extension KMMainViewController {
  1874. //文件对比
  1875. func openContentCompareVC(with pdfCompareContent: CPDFCompareContent?, results: [CPDFCompareResults], oldDocument: CPDFDocument, document: CPDFDocument) {
  1876. self.isCompareModel = true
  1877. let compareContentView = KMCompareContentView()
  1878. compareContentView.oldDocument = oldDocument
  1879. compareContentView.document = document
  1880. compareContentView.compareResults = results
  1881. compareContentView.saveHandle = { [unowned self] view in
  1882. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) { [unowned self] in
  1883. let saveController = KMCompareSaveWindow(windowNibName: "KMCompareSaveWindow")
  1884. self.currentWindowController = saveController
  1885. saveController.cancelHandle = { [unowned self] controller in
  1886. self.view.window!.endSheet(controller.window!)
  1887. self.currentWindowController = nil
  1888. }
  1889. saveController.saveHandle = { [unowned self] controller, saveType in
  1890. let folderPath = controller.fileSaveFolderPath
  1891. if folderPath != nil {
  1892. if !FileManager.default.fileExists(atPath: folderPath) {
  1893. try? FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil)
  1894. }
  1895. #if VERSION_DMG
  1896. #else
  1897. let url = URL(fileURLWithPath: folderPath)
  1898. let fileAccess = AppSandboxFileAccess()
  1899. fileAccess?.persistPermissionURL(url)
  1900. if let bookmarkData = try?url.bookmarkData(options: [.withSecurityScope]) {
  1901. fileAccess?.bookmarkPersistanceDelegate.setBookmarkData(bookmarkData, for: url)
  1902. let urlString = url.path
  1903. let _url = URL(fileURLWithPath: urlString)
  1904. fileAccess?.bookmarkPersistanceDelegate.setBookmarkData(bookmarkData, for: _url)
  1905. }
  1906. #endif
  1907. var savePath: String
  1908. switch saveType {
  1909. case 0:
  1910. let filePath = oldDocument.documentURL.path
  1911. let fileName = filePath.deletingPathExtension.lastPathComponent
  1912. savePath = "\(folderPath)/\(fileName)_compare\(filePath.extension)"
  1913. savePath = self.getValidFilePath(savePath)
  1914. oldDocument.write(to: URL(fileURLWithPath: savePath))
  1915. NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
  1916. case 1:
  1917. let filePath = document.documentURL.path
  1918. let fileName = filePath.deletingPathExtension.lastPathComponent
  1919. savePath = "\(folderPath)/\(fileName)_compare\(filePath.extension)"
  1920. savePath = self.getValidFilePath(savePath)
  1921. document.write(to: URL(fileURLWithPath: savePath))
  1922. NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
  1923. case 2:
  1924. let filePath = oldDocument.documentURL.path
  1925. let fileName = filePath.deletingPathExtension.lastPathComponent
  1926. savePath = "\(folderPath)/MergedCompareFile\(filePath.extension)"
  1927. savePath = self.getValidFilePath(savePath)
  1928. pdfCompareContent!.saveAsComparisonDocument(withFilePath: savePath)
  1929. NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
  1930. default:
  1931. break
  1932. }
  1933. }
  1934. self.view.window!.endSheet(controller.window!)
  1935. self.currentWindowController = nil
  1936. }
  1937. NSWindow.currentWindow().beginSheet(saveController.window!)
  1938. }
  1939. }
  1940. compareContentView.closeHandle = { [unowned self] view in
  1941. self.isCompareModel = false
  1942. view.removeFromSuperview()
  1943. }
  1944. compareContentView.autoresizingMask = [.width,.height]
  1945. }
  1946. func openCoveringCompareVC(with pdfDocument: CPDFDocument) {
  1947. self.isCompareModel = true
  1948. let coveringView = KMCompareCoveringView()
  1949. coveringView.pdfDocument = pdfDocument
  1950. coveringView.closeHandle = { [unowned self] view in
  1951. self.isCompareModel = false
  1952. view.removeFromSuperview()
  1953. }
  1954. coveringView.saveHandle = { [unowned self] view in
  1955. let savePanel = NSSavePanel()
  1956. savePanel.nameFieldStringValue = "untitled"
  1957. savePanel.allowedFileTypes = ["pdf"]
  1958. savePanel.beginSheetModal(for: NSWindow.currentWindow()) { result in
  1959. if result == .OK {
  1960. pdfDocument.write(to: savePanel.url!)
  1961. NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!])
  1962. }
  1963. }
  1964. }
  1965. coveringView.autoresizingMask = [.width,.height]
  1966. }
  1967. func getValidFilePath(_ oldPath: String) -> String {
  1968. let fileManager = FileManager.default
  1969. do {
  1970. let fileAttributes = try fileManager.attributesOfItem(atPath: oldPath)
  1971. guard let fileType = fileAttributes[FileAttributeKey.type] as? String else {
  1972. return oldPath
  1973. }
  1974. var i = 1
  1975. var newPath = oldPath
  1976. while fileManager.fileExists(atPath: newPath) {
  1977. if fileType == FileAttributeType.typeDirectory.rawValue {
  1978. newPath = oldPath + "(\(i))"
  1979. } else {
  1980. let fileExtension = (oldPath as NSString).pathExtension
  1981. newPath = ((oldPath as NSString).deletingPathExtension as NSString).appendingFormat("(\(i)).\(fileExtension)" as NSString) as String
  1982. }
  1983. i += 1
  1984. }
  1985. return newPath
  1986. } catch {
  1987. print("Error getting file attributes: \(error)")
  1988. return oldPath
  1989. }
  1990. }
  1991. }
  1992. extension KMMainViewController {
  1993. func documentAllowsEdit() -> Bool {
  1994. if (self.listView.document.allowsCopying == false || self.listView.document.allowsPrinting == false) {
  1995. let alert = NSAlert()
  1996. alert.alertStyle = .critical
  1997. alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")
  1998. alert.runModal()
  1999. return false
  2000. } else {
  2001. return true
  2002. }
  2003. }
  2004. func changeFont(_ sender: NSFontManager) {
  2005. KMPrint("changeFont ...")
  2006. if ((self.listView.activeAnnotation?.isKind(of: CPDFFreeTextAnnotation.self)) != nil) {
  2007. let annotation: CPDFFreeTextAnnotation = self.listView.activeAnnotation as! CPDFFreeTextAnnotation
  2008. var font = NSFont(name: annotation.fontName() ?? "Helvetica", size: (annotation.fontSize()) )
  2009. font = sender.convert(font!)
  2010. annotation.fontSize = font?.pointSize ?? 12
  2011. self.listView.commitEditAnnotationFreeText(annotation)
  2012. self.listView.setNeedsDisplay(annotation)
  2013. }
  2014. }
  2015. func currentSetup() -> [String: Any] {
  2016. var setup: [String: Any] = [:]
  2017. var point = NSZeroPoint
  2018. if listView == nil {
  2019. return setup
  2020. }
  2021. let pageIndex = listView.currentPageIndexAndPoint(&point, rotated: nil)
  2022. setup[kWindowFrameKey] = NSStringFromRect(mainWindow?.frame ?? NSZeroRect)
  2023. setup[KMMainModel.Key.kLeftSidePaneWidth] = self.model.lastLeftPanWidth
  2024. setup[KMMainModel.Key.kRightSidePaneWidth] = self.model.lastRightPanWidth
  2025. setup[KMMainModel.Key.pageIndex] = pageIndex
  2026. return setup
  2027. }
  2028. @objc func didAddContentViewNotification(_ sender: Notification) {
  2029. guard let win = sender.object as? NSWindow, win.isEqual(to: self.view.window) else {
  2030. return
  2031. }
  2032. if self.interactionMode == .presentation {
  2033. }
  2034. }
  2035. //!!!: - CPDFFreeTextAnnotation 空注释时会删除,删除时sdk内部删除的,只能接受通知来刷选UI【正常的注释删除会走两遍】
  2036. @objc func didRemoveAnnotationNotification(_ sender: Notification) {
  2037. guard let anno = sender.object as? CPDFAnnotation else {
  2038. return
  2039. }
  2040. if anno.page?.document != self.listView.document {
  2041. return
  2042. }
  2043. }
  2044. // MARK: Split View
  2045. func changePDFDocument(isChange: Bool, replaceBlock: @escaping (String) -> Void) {
  2046. let openPanel = NSOpenPanel()
  2047. openPanel.allowedFileTypes = ["pdf", "PDF"]
  2048. openPanel.allowsMultipleSelection = false
  2049. guard let mainWindow = NSApp.mainWindow else {
  2050. return
  2051. }
  2052. openPanel.beginSheetModal(for: mainWindow) { [weak self] response in
  2053. if response == NSApplication.ModalResponse.OK {
  2054. guard let url = openPanel.url else {
  2055. return
  2056. }
  2057. if let document = CPDFDocument(url: url) {
  2058. replaceBlock(document.documentURL?.path ?? "")
  2059. } else {
  2060. let alert = NSAlert()
  2061. alert.alertStyle = .critical
  2062. alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
  2063. alert.runModal()
  2064. }
  2065. }
  2066. }
  2067. }
  2068. }