KMNPopAnnotationViewController.swift 52 KB

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