KMNPopAnnotationViewController.swift 51 KB

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