KMNPopOperationWindowController.swift 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  1. //
  2. // KMNPopOperationWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by 丁林圭 on 2024/12/2.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. let popOffSet:CGFloat = 8.0
  10. typealias PaneCallback = (_ isOpenPane: Bool) -> ()
  11. typealias UpdatePDFViewCallback = () -> ()
  12. class KMNPopOperationWindowController: KMNBaseWindowController {
  13. public var popType:ListViewPopType = .popTypeNone {
  14. didSet {
  15. rightOffsetConstraint.constant = 45.0
  16. operationHeightConstraint.constant = 32.0
  17. paneBox.isHidden = false
  18. switch popType {
  19. case .generaAnnotation :
  20. generaPopView.layoutSubtreeIfNeeded()
  21. operationWidthConstraint.constant = generaPopView.bounds.width
  22. self.window?.display() //需刷新约束才会有值,不然会变化
  23. operationBox.contentView = generaPopView
  24. break
  25. case .freeTextAnnotation:
  26. fontPopView.layoutSubtreeIfNeeded()
  27. operationWidthConstraint.constant = fontPopView.bounds.width
  28. self.window?.display() //需刷新约束才会有值,不然会变化
  29. operationBox.contentView = fontPopView
  30. break
  31. case .shapeAnnotation:
  32. shapeView.layoutSubtreeIfNeeded()
  33. operationWidthConstraint.constant = shapeView.bounds.width
  34. self.window?.display() //需刷新约束才会有值,不然会变化
  35. operationBox.contentView = shapeView
  36. break
  37. case .linkAnnotation:
  38. linkType = .linkSetting
  39. break
  40. case .formAnnotation:
  41. formRightConstraint.constant = 0
  42. gropNameInput.isHidden = true
  43. formView.layoutSubtreeIfNeeded()
  44. operationWidthConstraint.constant = formView.bounds.width
  45. self.window?.display() //需刷新约束才会有值,不然会变化
  46. operationBox.contentView = formView
  47. break
  48. case .formRadioAnnotation:
  49. formRightConstraint.constant = 110
  50. gropNameInput.isHidden = false
  51. formView.layoutSubtreeIfNeeded()
  52. operationWidthConstraint.constant = formView.bounds.width
  53. self.window?.display() //需刷新约束才会有值,不然会变化
  54. operationBox.contentView = formView
  55. break
  56. case .multpleAnnotation:
  57. alightView.layoutSubtreeIfNeeded()
  58. operationWidthConstraint.constant = alightView.bounds.width
  59. self.window?.display() //需刷新约束才会有值,不然会变化
  60. operationBox.contentView = alightView
  61. break
  62. case .popTypeNone:
  63. break
  64. }
  65. }
  66. }
  67. public var isOpenPane = false {
  68. didSet {
  69. if isOpenPane == true {
  70. paneSelectorItem.properties.state = .pressed
  71. } else {
  72. paneSelectorItem.properties.state = .normal
  73. }
  74. paneSelectorItem.reloadData()
  75. }
  76. }
  77. public var annotationPopMode:KMNAnnotationPopMode = KMNAnnotationPopMode(pdfAnnotations: []) {
  78. didSet {
  79. let annotationPopType = annotationPopMode.popType
  80. popType = annotationPopType
  81. if annotationPopType == .generaAnnotation {
  82. let newColor = annotationPopMode.annotationColor()
  83. let oldColor = annotationColor
  84. if !CPDFListView.isTheSameColor(newColor, anotherColor: oldColor) {
  85. annotationColor = newColor
  86. }
  87. } else if(annotationPopType == .shapeAnnotation) {
  88. let newColor = annotationPopMode.annotationColor()
  89. let oldColor = annotationColor
  90. if !CPDFListView.isTheSameColor(newColor, anotherColor: oldColor) {
  91. annotationColor = newColor
  92. }
  93. } else if(annotationPopType == .freeTextAnnotation) {
  94. let newColor = annotationPopMode.annotationFontColor()
  95. let oldColor = fontColor
  96. if !CPDFListView.isTheSameColor(newColor, anotherColor: oldColor) {
  97. fontColor = newColor
  98. }
  99. let alignment = annotationPopMode.annotationAlignment()
  100. if(alignment != self.fontAlight) {
  101. fontAlight = alignment
  102. }
  103. let font = annotationPopMode.annotationFontName()
  104. if(font?.familyName != compdfFont?.familyName || font?.styleName != compdfFont?.styleName) {
  105. compdfFont = font
  106. }
  107. } else if annotationPopType == .linkAnnotation {
  108. if annotationPopMode.annotation != nil {
  109. linkAnnotation = annotationPopMode.annotation as! CPDFLinkAnnotation
  110. }
  111. } else if annotationPopType == .formAnnotation {
  112. if annotationPopMode.annotationFieldName() != fildNameString {
  113. fildNameString = annotationPopMode.annotationFieldName() ?? ""
  114. }
  115. } else if annotationPopType == .formRadioAnnotation {
  116. if annotationPopMode.annotationFieldName() != fildNameString {
  117. fildNameString = annotationPopMode.annotationFieldName() ?? ""
  118. }
  119. if annotationPopMode.annotationGropName() != gropNameString {
  120. gropNameString = annotationPopMode.annotationGropName() ?? ""
  121. }
  122. }
  123. }
  124. }
  125. private var annotationColor:NSColor?{
  126. didSet {
  127. if popType == .generaAnnotation {
  128. generaColorGroup.currentColor = annotationColor
  129. generaColorGroup.refreshUI()
  130. } else if popType == .shapeAnnotation {
  131. shapeColorGroup.currentColor = annotationColor
  132. shapeColorGroup.refreshUI()
  133. }
  134. }
  135. }
  136. private var fontColor:NSColor?{
  137. didSet {
  138. fontColorItem.properties?.color = fontColor
  139. fontColorItem.reloadData()
  140. }
  141. }
  142. private var linkAnnotation:CPDFLinkAnnotation = CPDFLinkAnnotation(){
  143. didSet {
  144. }
  145. }
  146. private var fildNameString:String = ""{
  147. didSet {
  148. fildNameInput.properties.text = fildNameString
  149. fildNameInput.reloadData()
  150. }
  151. }
  152. private var gropNameString:String = ""{
  153. didSet {
  154. gropNameInput.properties.text = gropNameString
  155. gropNameInput.reloadData()
  156. }
  157. }
  158. private var compdfFont:CPDFFont?{
  159. didSet {
  160. if(compdfFont != nil) {
  161. let styleName = compdfFont!.styleName
  162. if(styleName?.isEmpty == true) {
  163. fontNameSelect.properties.text = compdfFont!.familyName
  164. } else {
  165. fontNameSelect.properties.text = compdfFont!.familyName + "-" + (compdfFont!.styleName ?? "")
  166. }
  167. } else {
  168. fontNameSelect.properties.text = "-"
  169. }
  170. fontNameSelect.selectItemAtIndex(0)
  171. fontNameSelect.reloadData()
  172. }
  173. }
  174. private var fontAlight:NSTextAlignment = .left {
  175. didSet {
  176. if fontAlight == .center {
  177. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightCenter")
  178. } else if fontAlight == .right {
  179. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightRight")
  180. } else {
  181. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightLeft")
  182. }
  183. fontAlightButton.reloadData()
  184. }
  185. }
  186. private var objectAlignType:ObjectAlignType = .alightLeft {
  187. didSet {
  188. var zeroRect = NSRect.null
  189. var highestRect = NSZeroRect
  190. var widthestRect = NSZeroRect
  191. let objects = annotationPopMode.annotations
  192. let fristObject : CPDFAnnotation = objects.first ?? CPDFAnnotation()
  193. var leftestRect = fristObject.bounds
  194. var rightestRect = fristObject.bounds
  195. var topestRect = fristObject.bounds
  196. var bottomestRect = fristObject.bounds
  197. var leftestObject : CPDFAnnotation = fristObject
  198. var rightestObject : CPDFAnnotation = fristObject
  199. var topestObject : CPDFAnnotation = fristObject
  200. var bottomestObject: CPDFAnnotation = fristObject
  201. var totalWidth = 0.0
  202. var totalHeight = 0.0
  203. for i in 0 ..< objects.count {
  204. let annotation : CPDFAnnotation = objects[i]
  205. zeroRect = zeroRect.union(annotation.bounds)
  206. totalWidth = totalWidth + annotation.bounds.width
  207. totalHeight = totalHeight + annotation.bounds.height
  208. if annotation.bounds.height > highestRect.height {
  209. highestRect = annotation.bounds
  210. }
  211. if annotation.bounds.width > widthestRect.width {
  212. widthestRect = annotation.bounds
  213. }
  214. if leftestRect.minX > annotation.bounds.minX {
  215. leftestRect = annotation.bounds
  216. leftestObject = annotation
  217. }
  218. if annotation.bounds.maxX > rightestRect.maxX {
  219. rightestRect = annotation.bounds
  220. rightestObject = annotation
  221. }
  222. if annotation.bounds.maxY > topestRect.maxY {
  223. topestRect = annotation.bounds
  224. topestObject = annotation
  225. }
  226. if bottomestRect.minY > annotation.bounds.minY {
  227. bottomestRect = annotation.bounds
  228. bottomestObject = annotation
  229. }
  230. }
  231. var resultAreasArray: [CPDFAnnotation] = []
  232. var newBoundsArray: [String] = []
  233. switch objectAlignType {
  234. case .alightLeft :
  235. for i in 0 ..< objects.count {
  236. let object = objects[i]
  237. var bounds = object.bounds
  238. bounds.origin.x = zeroRect.origin.x
  239. newBoundsArray.append(NSStringFromRect(bounds))
  240. }
  241. resultAreasArray = objects
  242. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightLeft")
  243. break
  244. case .alightRight:
  245. for i in 0 ..< objects.count {
  246. let object = objects[i]
  247. var bounds = object.bounds
  248. bounds.origin.x = zeroRect.maxX - bounds.size.width
  249. newBoundsArray.append(NSStringFromRect(bounds))
  250. }
  251. resultAreasArray = objects
  252. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightRight")
  253. break
  254. case .alightTop:
  255. for i in 0 ..< objects.count {
  256. let object = objects[i]
  257. var bounds = object.bounds
  258. bounds.origin.y = zeroRect.maxY - bounds.size.height
  259. newBoundsArray.append(NSStringFromRect(bounds))
  260. }
  261. resultAreasArray = objects
  262. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightTop")
  263. break
  264. case .alightVer:
  265. for i in 0 ..< objects.count {
  266. let object = objects[i]
  267. var bounds = object.bounds
  268. bounds.origin.x = widthestRect.midX - bounds.width/2
  269. newBoundsArray.append(NSStringFromRect(bounds))
  270. }
  271. resultAreasArray = objects
  272. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightVer")
  273. break
  274. case .alightHor:
  275. for i in 0 ..< objects.count {
  276. let object = objects[i]
  277. var bounds = object.bounds
  278. bounds.origin.y = highestRect.midY - bounds.height/2
  279. newBoundsArray.append(NSStringFromRect(bounds))
  280. }
  281. resultAreasArray = objects
  282. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightHor")
  283. break
  284. case .alightBottom:
  285. for i in 0 ..< objects.count {
  286. let object = objects[i]
  287. var bounds = object.bounds
  288. bounds.origin.y = zeroRect.minY
  289. newBoundsArray.append(NSStringFromRect(bounds))
  290. }
  291. resultAreasArray = objects
  292. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightBottom")
  293. break
  294. case .averageVer:
  295. let middleGap = zeroRect.height - topestRect.height - bottomestRect.height
  296. let otherAreasTotalHeight = totalHeight - topestRect.height - bottomestRect.height
  297. let gap = (middleGap - otherAreasTotalHeight)/CGFloat(objects.count - 1)
  298. var areasCopyArray : [CPDFAnnotation] = objects
  299. areasCopyArray.sorted(by: { obj1, obj2 in
  300. let area1 = obj1
  301. let area2 = obj2
  302. if area1.bounds.origin.x < area2.bounds.origin.x {
  303. return true
  304. } else {
  305. return false
  306. }
  307. })
  308. if let index = areasCopyArray.firstIndex(of: topestObject) {
  309. areasCopyArray.remove(at: index)
  310. }
  311. if let index = areasCopyArray.firstIndex(of: bottomestObject) {
  312. areasCopyArray.remove(at: index)
  313. }
  314. var bottomStartY = bottomestRect.maxY + gap
  315. for i in 0 ..< areasCopyArray.count {
  316. let areas = areasCopyArray[i]
  317. var bounds = areas.bounds
  318. bounds.origin.y = bottomStartY
  319. newBoundsArray.append(NSStringFromRect(bounds))
  320. bottomStartY = bottomStartY + bounds.height + gap
  321. }
  322. resultAreasArray = areasCopyArray
  323. alightButton.properties.icon = NSImage(named: "KMNImageNameObjecAlignAverageVer")
  324. break
  325. case .averageHor:
  326. let middleGap = zeroRect.width - leftestRect.width - rightestRect.width
  327. let otherAreasTotalWidth = totalWidth - leftestRect.width - rightestRect.width
  328. let gap = (middleGap - otherAreasTotalWidth)/CGFloat(objects.count - 1)
  329. var areasCopyArray : [CPDFAnnotation] = objects
  330. areasCopyArray.sorted(by: { obj1, obj2 in
  331. let area1 = obj1
  332. let area2 = obj2
  333. if area1.bounds.origin.x < area2.bounds.origin.x {
  334. return true
  335. } else {
  336. return false
  337. }
  338. })
  339. if let index = areasCopyArray.firstIndex(of: leftestObject) {
  340. areasCopyArray.remove(at: index)
  341. }
  342. if let index = areasCopyArray.firstIndex(of: rightestObject) {
  343. areasCopyArray.remove(at: index)
  344. }
  345. var leftStartX = leftestRect.maxX + gap
  346. for i in 0 ..< areasCopyArray.count {
  347. let areas = areasCopyArray[i]
  348. var bounds = areas.bounds
  349. bounds.origin.x = leftStartX
  350. newBoundsArray.append(NSStringFromRect(bounds))
  351. leftStartX = leftStartX + bounds.width + gap
  352. }
  353. resultAreasArray = areasCopyArray
  354. alightButton.properties.icon = NSImage(named: "KMNImageNameObjecAlignAverageHor")
  355. break
  356. }
  357. alightButton.reloadData()
  358. for i in 0 ..< resultAreasArray.count {
  359. let annotation : CPDFAnnotation = resultAreasArray[i]
  360. annotation.bounds = NSRectFromString(newBoundsArray[i])
  361. }
  362. }
  363. }
  364. var paneCallback: PaneCallback?
  365. var updatePDFViewCallback: UpdatePDFViewCallback?
  366. static let shared: KMNPopOperationWindowController = {
  367. let windowC = KMNPopOperationWindowController(windowNibName: "KMNPopOperationWindowController")
  368. return windowC
  369. }()
  370. var linkType:linkDetailType = .linkSetting {
  371. didSet {
  372. if linkType == .linkSetting {
  373. linkView.layoutSubtreeIfNeeded()
  374. rightOffsetConstraint.constant = 45.0
  375. operationHeightConstraint.constant = 32.0
  376. operationWidthConstraint.constant = linkView.bounds.width
  377. self.window?.display() //需刷新约束才会有值,不然会变化
  378. operationBox.contentView = linkView
  379. paneBox.isHidden = false
  380. } else if linkType == .page {
  381. linkPageDetailView.layoutSubtreeIfNeeded()
  382. rightOffsetConstraint.constant = 8
  383. operationWidthConstraint.constant = linkPageDetailView.bounds.width
  384. operationHeightConstraint.constant = linkPageDetailView.bounds.height
  385. self.window?.display() //需刷新约束才会有值,不然会变化
  386. operationBox.contentView = linkPageDetailView
  387. paneBox.isHidden = true
  388. configUrlPopUI()
  389. } else if linkType == .url {
  390. linkUrlDetailView.layoutSubtreeIfNeeded()
  391. rightOffsetConstraint.constant = 8
  392. operationWidthConstraint.constant = linkUrlDetailView.bounds.width
  393. operationHeightConstraint.constant = linkUrlDetailView.bounds.height
  394. self.window?.display() //需刷新约束才会有值,不然会变化
  395. operationBox.contentView = linkUrlDetailView
  396. paneBox.isHidden = true
  397. configUrlPopUI()
  398. } else if linkType == .email {
  399. linkUrlDetailView.layoutSubtreeIfNeeded()
  400. rightOffsetConstraint.constant = 8
  401. operationWidthConstraint.constant = linkUrlDetailView.bounds.width
  402. operationHeightConstraint.constant = linkUrlDetailView.bounds.height
  403. self.window?.display() //需刷新约束才会有值,不然会变化
  404. operationBox.contentView = linkUrlDetailView
  405. paneBox.isHidden = true
  406. configUrlPopUI()
  407. }
  408. updateFrame(listView: listView ?? CPDFListView())
  409. }
  410. }
  411. @IBOutlet weak var contentBox: NSBox!
  412. @IBOutlet weak var operationBox: NSBox!
  413. @IBOutlet weak var paneBox: NSBox!
  414. @IBOutlet weak var lineBox: NSBox!
  415. @IBOutlet var paneSelectorItem: ComponentCSelector!
  416. @IBOutlet weak var operationWidthConstraint: NSLayoutConstraint!
  417. @IBOutlet weak var rightOffsetConstraint: NSLayoutConstraint!
  418. @IBOutlet weak var operationHeightConstraint: NSLayoutConstraint!
  419. @IBOutlet var generaPopView: NSView!
  420. @IBOutlet var generaColorGroup: ComponentCColorGroup!
  421. @IBOutlet var fontPopView: NSView!
  422. @IBOutlet var fontColorItem: ComponentCColorItem!
  423. @IBOutlet var fontNameSelect: ComponentSelect!
  424. @IBOutlet var fontSizeZoomOutButton: ComponentButton!
  425. @IBOutlet var fontSizeZoomInButton: ComponentButton!
  426. @IBOutlet var fontAlightButton: ComponentButton!
  427. @IBOutlet var shapeView: NSView!
  428. @IBOutlet var shapeColorGroup: ComponentCColorGroup!
  429. @IBOutlet var widthZoomOutButton: ComponentButton!
  430. @IBOutlet var widthZoomInButton: ComponentButton!
  431. @IBOutlet var linkView: NSView!
  432. @IBOutlet var pageLinkButton: ComponentButton!
  433. @IBOutlet var urlLinkButton: ComponentButton!
  434. @IBOutlet var emailLinkButton: ComponentButton!
  435. @IBOutlet weak var pageLinkWidthConstraint: NSLayoutConstraint!
  436. @IBOutlet weak var urlLinkWidthConstraint: NSLayoutConstraint!
  437. @IBOutlet weak var emailLinkWidthConstraint: NSLayoutConstraint!
  438. @IBOutlet var formView: NSView!
  439. @IBOutlet var fildNameInput: ComponentInput!
  440. @IBOutlet var gropNameInput: ComponentInput!
  441. @IBOutlet var formRightConstraint: NSLayoutConstraint!
  442. @IBOutlet var alightView: NSView!
  443. @IBOutlet var alightButton: ComponentButton!
  444. @IBOutlet var linkPageDetailView: NSView!
  445. @IBOutlet var backPageLinkButton: ComponentButton!
  446. @IBOutlet var paginationView: ComponentPagination!
  447. @IBOutlet var paginationDesBox: NSBox!
  448. @IBOutlet var pageThumImageView: NSImageView!
  449. @IBOutlet var goPageLinkButton: ComponentButton!
  450. @IBOutlet weak var backPageWidthConstraint: NSLayoutConstraint!
  451. @IBOutlet var linkUrlDetailView: NSView!
  452. @IBOutlet var backUrlLinkButton: ComponentButton!
  453. @IBOutlet var goUrlLinkButton: ComponentButton!
  454. @IBOutlet var urlInput: ComponentInput!
  455. @IBOutlet weak var backUrlWidthConstraint: NSLayoutConstraint!
  456. var fontPopover:NSPopover?
  457. var ObjectPopover:NSPopover?
  458. weak var listView:CPDFListView?
  459. override func windowDidLoad() {
  460. super.windowDidLoad()
  461. }
  462. override func initContentView() {
  463. super.initContentView()
  464. configFormPopUI()
  465. congfigFontPopUI()
  466. congfigGeneraPopUI()
  467. congfigShapePopUI()
  468. paneSelectorItem.properties = ComponentCSelectorProperty(iconImage:NSImage(named: "KMNImageNameListViewPopPane"))
  469. paneSelectorItem.setTarget(self, action: #selector(paneButtonClicked(_ :)))
  470. fontSizeZoomOutButton.properties = ComponentButtonProperty(type: .text_gray,
  471. size: .s,
  472. state: .normal,
  473. onlyIcon: true,
  474. icon:NSImage(named: "KMNImageNameListViewPopFontSizeZoomOut"),
  475. keepPressState: false)
  476. fontSizeZoomOutButton.setTarget(self, action: #selector(fontSizeZoomOutButtonClicked(_ :)))
  477. fontSizeZoomInButton.properties = ComponentButtonProperty(type: .text_gray,
  478. size: .s,
  479. state: .normal,
  480. onlyIcon: true,
  481. icon:NSImage(named: "KMNImageNameListViewPopFontSizeZoomIn"),
  482. keepPressState: false)
  483. fontSizeZoomInButton.setTarget(self, action: #selector(fontSizeZoomInButtonClicked(_ :)))
  484. fontAlightButton.properties = ComponentButtonProperty(type: .text_gray,
  485. size: .s,
  486. state: .normal,
  487. onlyIcon: true,
  488. icon:NSImage(named: "KMNImageNameListViewPopAlightLeft"))
  489. fontAlightButton.setTarget(self, action: #selector(fontAlightButtonClicked(_ :)))
  490. widthZoomOutButton.properties = ComponentButtonProperty(type: .text_gray,
  491. size: .s,
  492. state: .normal,
  493. onlyIcon: true,
  494. icon:NSImage(named: "KMNImageNameListViewPopWidthZoomOut"),
  495. keepPressState: false)
  496. widthZoomOutButton.setTarget(self, action: #selector(widthZoomOutButtonClicked(_ :)))
  497. widthZoomInButton.properties = ComponentButtonProperty(type: .text_gray,
  498. size: .s,
  499. state: .normal,
  500. onlyIcon: true,
  501. icon:NSImage(named: "KMNImageNameListViewPopWidthZoomIn"),
  502. keepPressState: false)
  503. widthZoomInButton.setTarget(self, action: #selector(widthZoomInButtonClicked(_ :)))
  504. pageLinkButton.setTarget(self, action: #selector(pageLinkButtonClicked(_ :)))
  505. urlLinkButton.setTarget(self, action: #selector(urlLinkButtonClicked(_ :)))
  506. emailLinkButton.setTarget(self, action: #selector(emailLinkButtonClicked(_ :)))
  507. alightButton.properties = ComponentButtonProperty(type: .text_gray,
  508. size: .s,
  509. state: .normal,
  510. onlyIcon: true,
  511. icon:NSImage(named: "KMNImageNameObjectPopAlightLeft"))
  512. alightButton.setTarget(self, action: #selector(alightButtonClicked(_ :)))
  513. goUrlLinkButton.properties = ComponentButtonProperty(type: .text_gray,
  514. size: .s,
  515. state: .normal,
  516. onlyIcon: true,
  517. icon:NSImage(named: "KMNImageNamePopLinkGO"),keepPressState: false)
  518. goUrlLinkButton.setTarget(self, action: #selector(linkGoButtonClicked(_ :)))
  519. goPageLinkButton.properties = ComponentButtonProperty(type: .text_gray,
  520. size: .s,
  521. state: .normal,
  522. onlyIcon: true,
  523. icon:NSImage(named: "KMNImageNamePopLinkGO"),keepPressState: false)
  524. goPageLinkButton.setTarget(self, action: #selector(linkGoButtonClicked(_ :)))
  525. paginationView.properties = ComponentPaginationProperty(doubleArrow_show: false, currentIndex: 0, totalCount: 1)
  526. paginationView.delegate = self
  527. }
  528. override func updateUIThemeColor() {
  529. super.updateUIThemeColor()
  530. lineBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/divider")
  531. contentBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/popup")
  532. contentBox.borderColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/3-default")
  533. paginationDesBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorFill/4")
  534. }
  535. override func updateUILanguage() {
  536. super.updateUILanguage()
  537. pageLinkButton.properties = ComponentButtonProperty(type: .text_gray,
  538. size: .s,
  539. state: .normal,
  540. onlyIcon: false,
  541. showLeftIcon:true,
  542. buttonText:KMLocalizedString("Page"),
  543. icon:NSImage(named: "KMNImageNameListViewLinkPage"),keepPressState: false)
  544. urlLinkButton.properties = ComponentButtonProperty(type: .text_gray,
  545. size: .s,
  546. state: .normal,
  547. onlyIcon: false,
  548. showLeftIcon:true,
  549. buttonText:KMLocalizedString("Web"),
  550. icon:NSImage(named: "KMNImageNameListViewLinkUrl"),keepPressState: false)
  551. emailLinkButton.properties = ComponentButtonProperty(type: .text_gray,
  552. size: .s,
  553. state: .normal,
  554. onlyIcon: false,
  555. showLeftIcon:true,
  556. buttonText:KMLocalizedString("Email"),
  557. icon:NSImage(named: "KMNImageNameListViewLinkEmail"),keepPressState: false)
  558. pageLinkWidthConstraint.constant = pageLinkButton.properties.propertyInfo.viewWidth
  559. urlLinkWidthConstraint.constant = urlLinkButton.properties.propertyInfo.viewWidth
  560. emailLinkWidthConstraint.constant = emailLinkButton.properties.propertyInfo.viewWidth
  561. backUrlLinkButton.properties = ComponentButtonProperty(type: .text_primary,
  562. size: .s,
  563. state: .normal,
  564. onlyIcon: false,
  565. showLeftIcon: true,
  566. buttonText: KMLocalizedString("Back"),
  567. icon:NSImage(named: "KMNImageNamePopLinkBack"),keepPressState: false)
  568. backUrlLinkButton.setTarget(self, action: #selector(linkBackButtonClicked(_ :)))
  569. backUrlWidthConstraint.constant = backUrlLinkButton.properties.propertyInfo.viewWidth
  570. backPageLinkButton.properties = ComponentButtonProperty(type: .text_primary,
  571. size: .s,
  572. onlyIcon: false,
  573. showLeftIcon:true,
  574. buttonText: KMLocalizedString("Back"),
  575. icon:NSImage(named: "KMNImageNamePopLinkBack"),keepPressState: false)
  576. backPageLinkButton.setTarget(self, action: #selector(linkBackButtonClicked(_ :)))
  577. backPageWidthConstraint.constant = backPageLinkButton.properties.propertyInfo.viewWidth
  578. }
  579. //MARK: - Public
  580. public func updateFrame(listView:CPDFListView) {
  581. let activeAnnotations = annotationPopMode.annotations
  582. let page = activeAnnotations.first?.page
  583. let windowFram = listView.window?.frame ?? CGRectZero
  584. if(page != nil) {
  585. let pageRect = listView.selectionMultipleBounds(with: activeAnnotations)
  586. let positioningRect = listView.convert(pageRect, from: page!)
  587. let view: NSView? = nil
  588. let position = listView.convert(positioningRect, to: view)
  589. var positionNew = position.origin
  590. positionNew.x += windowFram.origin.x + position.width/2
  591. positionNew.y += windowFram.origin.y + position.height
  592. var positionRect = self.window?.frame ?? CGRectZero
  593. positionRect.origin.x = positionNew.x - positionRect.width/2
  594. positionRect.origin.y = positionNew.y + popOffSet
  595. self.window?.setFrame(positionRect, display: true)
  596. }
  597. }
  598. //MARK: - private
  599. private func congfigGeneraPopUI() {
  600. var colors = KMAnnotationPropertiesColorManager.manager.markHighlightColors
  601. if(annotationPopMode.annotation is CPDFMarkupAnnotation) {
  602. let markupAnnotation:CPDFMarkupAnnotation = annotationPopMode.annotation as! CPDFMarkupAnnotation
  603. if markupAnnotation.markupType() == .highlight {
  604. colors = KMAnnotationPropertiesColorManager.manager.markHighlightColors
  605. } else {
  606. colors = KMAnnotationPropertiesColorManager.manager.markOtherColors
  607. }
  608. }
  609. let colorAProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[0])
  610. let colorBProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[1])
  611. let colorCProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[2])
  612. let colorDProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[3])
  613. let colorEProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: true, color: colors[4])
  614. generaColorGroup.setUpWithColorPropertys([colorAProperty, colorBProperty, colorCProperty, colorDProperty], customItemProperty: colorEProperty)
  615. generaColorGroup.delegate = self
  616. }
  617. private func congfigFontPopUI() {
  618. fontNameSelect.properties = ComponentSelectProperties(size: .s,
  619. state: .normal,
  620. isDisabled: false,
  621. isError: false,
  622. leftIcon: false,
  623. placeholder: nil,
  624. errorText: nil,
  625. creatable: false,
  626. text: NSLocalizedString("", comment: ""))
  627. fontNameSelect.delegate = self
  628. var menuItemArr: [ComponentMenuitemProperty] = []
  629. for familyName in CPDFFont.familyNames {
  630. let fontNames = CPDFFont.fontNames(forFamilyName: familyName)
  631. let itemProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  632. itemSelected: false,
  633. isDisabled: false,
  634. keyEquivalent: nil,
  635. text: familyName)
  636. var subMenuItemArr: [ComponentMenuitemProperty] = []
  637. for fontName in fontNames {
  638. let subItemProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  639. itemSelected: false,
  640. isDisabled: false,
  641. keyEquivalent: nil,
  642. text: fontName)
  643. subMenuItemArr.append(subItemProperty)
  644. }
  645. itemProperty.subPropertys = subMenuItemArr
  646. menuItemArr.append(itemProperty)
  647. }
  648. fontNameSelect.updateMenuItemsArr(menuItemArr)
  649. fontColorItem.properties = ComponentCColorProperty(colorType: .color,
  650. state: .normal,
  651. isCustom: true,
  652. color: NSColor.red)
  653. fontColorItem.delegate = self
  654. fontColorItem.reloadData()
  655. }
  656. private func congfigShapePopUI() {
  657. var colors = KMAnnotationPropertiesColorManager.manager.inkColors
  658. let annotation = annotationPopMode.annotation ?? CPDFAnnotation()
  659. if annotation.isKind(of: CPDFInkAnnotation.self) {
  660. colors = KMAnnotationPropertiesColorManager.manager.inkColors
  661. } else if annotation.isKind(of: CPDFCircleAnnotation.self) ||
  662. annotation.isKind(of: CPDFSquareAnnotation.self) {
  663. colors = KMAnnotationPropertiesColorManager.manager.inkColors
  664. } else if annotation.isKind(of: CPDFLineAnnotation.self) {
  665. if let lineAnnotation:CPDFLineAnnotation = annotation as? CPDFLineAnnotation {
  666. if lineAnnotation.isMeasure {
  667. colors = KMAnnotationPropertiesColorManager.manager.measureColors
  668. } else {
  669. colors = KMAnnotationPropertiesColorManager.manager.inkColors
  670. }
  671. }
  672. } else if (annotation.isKind(of: CPDFPolygonAnnotation.self) ||
  673. annotation.isKind(of: CPDFPolylineAnnotation.self)) {
  674. colors = KMAnnotationPropertiesColorManager.manager.measureColors
  675. } else if annotation.isKind(of: CPDFTextAnnotation.self) {
  676. colors = KMAnnotationPropertiesColorManager.manager.anchoredNoteColors
  677. } else if annotation.isKind(of: CSelfSignAnnotation.self) {
  678. colors = KMAnnotationPropertiesColorManager.manager.selfSignColors
  679. }
  680. let colorAProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[0])
  681. let colorBProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[1])
  682. let colorCProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[2])
  683. let colorDProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: colors[3])
  684. let colorEProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: true, color: colors[4])
  685. shapeColorGroup.setUpWithColorPropertys([colorAProperty, colorBProperty, colorCProperty, colorDProperty], customItemProperty: colorEProperty)
  686. shapeColorGroup.delegate = self
  687. }
  688. private func configFormPopUI() {
  689. let inputFiedProperty: ComponentInputProperty = ComponentInputProperty(size: .s,
  690. state:.pressed ,
  691. isError: false,
  692. showPrefix: false,
  693. showSuffix: false,
  694. showClear: false,
  695. isDisabled: false,
  696. placeholder: "File Name",
  697. text: "")
  698. fildNameInput.properties = inputFiedProperty
  699. fildNameInput.delegate = self
  700. let inputGropProperty: ComponentInputProperty = ComponentInputProperty(size: .s,
  701. state:.pressed ,
  702. isError: false,
  703. showPrefix: false,
  704. showSuffix: false,
  705. showClear: false,
  706. isDisabled: false,
  707. placeholder: "Grop Name",
  708. text: "")
  709. gropNameInput.properties = inputGropProperty
  710. gropNameInput.delegate = self
  711. }
  712. private func configUrlPopUI() {
  713. var placeholder = KMNCompanyWebsite
  714. if(linkType == .email) {
  715. placeholder = KMNCompanyEamil
  716. }
  717. let inputFiedProperty: ComponentInputProperty = ComponentInputProperty(size: .s,
  718. state:.pressed ,
  719. isError: false,
  720. showPrefix: false,
  721. showSuffix: false,
  722. showClear: false,
  723. isDisabled: false,
  724. placeholder: placeholder,
  725. text: "")
  726. urlInput.properties = inputFiedProperty
  727. urlInput.delegate = self
  728. if let destination = linkAnnotation.destination() {
  729. reloadPageUrlData()
  730. refreshPageThum()
  731. } else if let annotationURL = linkAnnotation.url(){
  732. var urlString = annotationURL.fileURL.absoluteString
  733. if annotationURL.hasPrefix("mailto:") {
  734. let trimmedString = String(urlString.suffix(from: urlString.index(urlString.startIndex, offsetBy: 7)))
  735. urlInput.properties.text = trimmedString
  736. } else {
  737. urlInput.properties.text = urlString
  738. }
  739. }
  740. paginationView.properties.totalCount = Int(listView?.document.pageCount ?? 1)
  741. }
  742. private func reloadPageUrlData() {
  743. guard let destination = linkAnnotation.destination() else {
  744. return
  745. }
  746. guard let page = destination.page() else {
  747. return
  748. }
  749. paginationView.properties.currentIndex = Int((page.pageIndex() + 1))
  750. paginationView.reloadData()
  751. }
  752. private func refreshPageThum() {
  753. guard let pdfView = listView else {
  754. return
  755. }
  756. guard let destination = linkAnnotation.destination() else {
  757. return
  758. }
  759. guard let page = destination.page() else {
  760. return
  761. }
  762. let thumbnail = KMNThumbnail.init(document: pdfView.document, currentPageIndex:Int(page.pageIndex()))
  763. thumbnail.generateThumImage {[weak self] image in
  764. self?.pageThumImageView.image = image
  765. }
  766. }
  767. //MARK: - Action
  768. @objc func paneButtonClicked(_ sender: NSView) {
  769. isOpenPane = !isOpenPane
  770. paneCallback?(isOpenPane)
  771. }
  772. @objc func fontSizeZoomOutButtonClicked(_ sender: NSView) {
  773. if let freeText = annotationPopMode.annotation as? CPDFFreeTextAnnotation {
  774. if listView?.isEdit(withCurrentFreeText: freeText) == true {
  775. listView?.commitEditAnnotationFreeText(freeText)
  776. }
  777. if annotationPopMode.zoomOutFontSize() {
  778. updatePDFViewCallback?()
  779. }
  780. }
  781. }
  782. @objc func fontSizeZoomInButtonClicked(_ sender: NSView) {
  783. if let freeText = annotationPopMode.annotation as? CPDFFreeTextAnnotation {
  784. if listView?.isEdit(withCurrentFreeText: freeText) == true {
  785. listView?.commitEditAnnotationFreeText(freeText)
  786. }
  787. if annotationPopMode.zoomInFontSize() {
  788. updatePDFViewCallback?()
  789. }
  790. }
  791. }
  792. @objc func fontAlightButtonClicked(_ sender: NSView) {
  793. if fontPopover?.isShown == true {
  794. fontPopover?.close()
  795. } else {
  796. let vc = KMNPopDetailsViewController(nibName: "KMNPopDetailsViewController", bundle: nil)
  797. let createFilePopover: NSPopover = NSPopover.init()
  798. createFilePopover.contentViewController = vc
  799. createFilePopover.delegate = self
  800. createFilePopover.animates = true
  801. createFilePopover.behavior = .semitransient
  802. createFilePopover.setValue(true, forKey: "shouldHideAnchor")
  803. createFilePopover.show(relativeTo: CGRect(x: sender.bounds.origin.x, y: 20, width: sender.bounds.size.width, height: sender.bounds.size.height), of: sender, preferredEdge: .maxY)
  804. vc.detailPopType = .freeTextAlight
  805. vc.fontChangeAlighCallback = { [weak self] alight in
  806. if let freeText = self?.annotationPopMode.annotation as? CPDFFreeTextAnnotation {
  807. if self?.listView?.isEdit(withCurrentFreeText: freeText) == true {
  808. self?.listView?.commitEditAnnotationFreeText(freeText)
  809. }
  810. }
  811. self?.annotationPopMode.setAnnotationAlignment(annotationAlignment: alight)
  812. self?.updatePDFViewCallback?()
  813. self?.fontAlight = alight
  814. }
  815. fontPopover = createFilePopover
  816. vc.fontAlight = fontAlight
  817. }
  818. }
  819. @objc func widthZoomOutButtonClicked(_ sender: NSView) {
  820. if annotationPopMode.zoomOutShapeWidth() {
  821. updatePDFViewCallback?()
  822. }
  823. }
  824. @objc func widthZoomInButtonClicked(_ sender: NSView) {
  825. if annotationPopMode.zoomInShapeWidth() {
  826. updatePDFViewCallback?()
  827. }
  828. }
  829. @objc func pageLinkButtonClicked(_ sender: NSView) {
  830. linkType = .page
  831. }
  832. @objc func urlLinkButtonClicked(_ sender: NSView) {
  833. linkType = .url
  834. }
  835. @objc func emailLinkButtonClicked(_ sender: NSView) {
  836. linkType = .email
  837. }
  838. @objc func alightButtonClicked(_ sender: NSView) {
  839. if ObjectPopover?.isShown == true {
  840. ObjectPopover?.close()
  841. } else {
  842. let vc = KMNPopDetailsViewController(nibName: "KMNPopDetailsViewController", bundle: nil)
  843. let createFilePopover: NSPopover = NSPopover.init()
  844. createFilePopover.contentViewController = vc
  845. createFilePopover.delegate = self
  846. createFilePopover.animates = true
  847. createFilePopover.behavior = .semitransient
  848. createFilePopover.setValue(true, forKey: "shouldHideAnchor")
  849. createFilePopover.show(relativeTo: CGRect(x: sender.bounds.origin.x, y: 20, width: sender.bounds.size.width, height: sender.bounds.size.height), of: sender, preferredEdge: .maxY)
  850. if (annotationPopMode.annotations.count == 2) {
  851. vc.detailPopType = .freeTextDoubleAlight
  852. } else if (annotationPopMode.annotations.count > 2) {
  853. vc.detailPopType = .freeTextMultpleAlight
  854. }
  855. vc.objectChangeAlighCallback = { [weak self] alight in
  856. self?.objectAlignType = alight
  857. self?.updatePDFViewCallback?()
  858. }
  859. ObjectPopover = createFilePopover
  860. vc.objectAlignType = objectAlignType
  861. }
  862. }
  863. @objc func linkGoButtonClicked(_ sender: NSView) {
  864. self.window?.resignFirstResponder()
  865. if linkType == .url {
  866. } else if linkType == .email {
  867. }
  868. }
  869. @objc func linkBackButtonClicked(_ sender: NSView) {
  870. self.window?.resignFirstResponder()
  871. linkType = .linkSetting
  872. }
  873. @objc func fontColorChange(_ sender: Any) {
  874. if let color = (sender as? NSColorPanel)?.color {
  875. if let freeText = annotationPopMode.annotation as? CPDFFreeTextAnnotation {
  876. if listView?.isEdit(withCurrentFreeText: freeText) == true {
  877. listView?.commitEditAnnotationFreeText(freeText)
  878. }
  879. }
  880. annotationPopMode.setAnnotationFontColor(annotationFontColor: color)
  881. fontColor = color
  882. updatePDFViewCallback?()
  883. }
  884. }
  885. }
  886. //MARK: - ComponentCColorDelegate
  887. extension KMNPopOperationWindowController: ComponentCColorDelegate {
  888. func componentCColorDidChooseColor(_ view: NSView, _ color: NSColor?) {
  889. if(view == generaColorGroup) {
  890. self.annotationPopMode.setAnnotationColor(annotationColor: color)
  891. updatePDFViewCallback?()
  892. } else if (view == shapeColorGroup) {
  893. self.annotationPopMode.setAnnotationColor(annotationColor: color)
  894. updatePDFViewCallback?()
  895. } else if (view == fontColorItem) {
  896. fontColorItem.properties?.state = .normal
  897. fontColorItem.reloadData()
  898. let colorPanel = NSColorPanel.shared
  899. colorPanel.setTarget(self)
  900. colorPanel.showsAlpha = false
  901. colorPanel.setAction(#selector(self.fontColorChange(_:)))
  902. colorPanel.orderFront(nil)
  903. }
  904. }
  905. }
  906. //MARK: - ComponentInputDelegate
  907. extension KMNPopOperationWindowController: ComponentInputDelegate {
  908. func componentInputDidChanged(inputView: ComponentInput) {
  909. if (inputView == fildNameInput) {
  910. } else if (inputView == gropNameInput) {
  911. } else if (inputView == urlInput) {
  912. }
  913. }
  914. func componentInputDidEndEditing(inputView: ComponentInput) {
  915. if (inputView == fildNameInput) {
  916. for i in 0 ..< annotationPopMode.annotations.count {
  917. let annotation = annotationPopMode.annotations[i]
  918. if let widgt = annotation as? CPDFWidgetAnnotation {
  919. widgt.setFieldName(inputView.properties.text)
  920. }
  921. }
  922. updatePDFViewCallback?()
  923. } else if (inputView == gropNameInput) {
  924. for i in 0 ..< annotationPopMode.annotations.count {
  925. let annotation = annotationPopMode.annotations[i]
  926. if let button = annotation as? CPDFButtonWidgetAnnotation {
  927. button.setButtonWidgetStateString(inputView.properties.text)
  928. }
  929. }
  930. updatePDFViewCallback?()
  931. } else if (inputView == urlInput) {
  932. if linkType == .url {
  933. } else if linkType == .email {
  934. }
  935. updatePDFViewCallback?()
  936. }
  937. }
  938. }
  939. //MARK: - ComponentSelectDelegate
  940. extension KMNPopOperationWindowController: ComponentSelectDelegate {
  941. func componentSelectDidSelect(view: ComponentSelect?, menuItemProperty: ComponentMenuitemProperty?) {
  942. if(view == fontNameSelect) {
  943. let familyName = fontNameSelect.properties.text ?? "Helvetica"
  944. let styles = CPDFFont.fontNames(forFamilyName: familyName)
  945. compdfFont = CPDFFont(familyName: familyName, fontStyle: styles.first ?? "")
  946. annotationPopMode.setAnnotationFont(font: compdfFont ?? CPDFFont.init(familyName: "Helvetica", fontStyle: ""))
  947. } else { //字体样式
  948. compdfFont = CPDFFont(familyName: compdfFont?.familyName ?? "Helvetica", fontStyle: menuItemProperty?.text ?? "")
  949. annotationPopMode.setAnnotationFont(font: compdfFont ?? CPDFFont.init(familyName: "Helvetica", fontStyle: ""))
  950. }
  951. }
  952. }
  953. //MARK: - ComponentSelectDelegate
  954. extension KMNPopOperationWindowController: NSPopoverDelegate {
  955. func popoverWillClose(_ notification: Notification) {
  956. if fontPopover == (notification.object as? NSPopover) {
  957. if(fontAlightButton.properties.state == .pressed) {
  958. fontAlightButton.properties.state = .normal
  959. fontAlightButton.reloadData()
  960. }
  961. } else if ObjectPopover == (notification.object as? NSPopover) {
  962. if(alightButton.properties.state == .pressed) {
  963. alightButton.properties.state = .normal
  964. alightButton.reloadData()
  965. }
  966. }
  967. }
  968. }
  969. //MARK: - ComponentPaginationDelegate
  970. extension KMNPopOperationWindowController: ComponentPaginationDelegate {
  971. public func componentPaginationDidValueChanged(pagination: ComponentPagination) {
  972. let pageIndex = pagination.properties.currentIndex
  973. let destination = CPDFDestination(document: listView?.document ?? CPDFDocument(), pageIndex: pageIndex - 1)
  974. linkAnnotation.setDestination(destination)
  975. refreshPageThum()
  976. reloadPageUrlData()
  977. }
  978. }