KMNPopAnnotationViewController.swift 50 KB

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