KMNPopContentEditWindowController.swift 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. //
  2. // KMNPopContentEditWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by 丁林圭 on 2024/12/2.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. class KMNPopContentEditWindowController: KMNBaseWindowController {
  10. public var editType:EditContentPopType = .editNone {
  11. didSet {
  12. rightOffsetConstraint.constant = 41.0
  13. paneBox.isHidden = false
  14. switch editType {
  15. case .signTextEdit :
  16. textPopView.layoutSubtreeIfNeeded()
  17. operationWidthConstraint.constant = textPopView.bounds.width
  18. self.window?.display() //需刷新约束才会有值,不然会变化
  19. operationBox.contentView = textPopView
  20. congfigFontPopUI()
  21. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightLeft")
  22. fontAlightButton.reloadData()
  23. break
  24. case .signImageEdit:
  25. imagePopView.layoutSubtreeIfNeeded()
  26. congfigSignImageUI()
  27. operationWidthConstraint.constant = imagePopView.bounds.width
  28. self.window?.display() //需刷新约束才会有值,不然会变化
  29. operationBox.contentView = imagePopView
  30. break
  31. case .multpleTextEdit:
  32. textPopView.layoutSubtreeIfNeeded()
  33. operationWidthConstraint.constant = textPopView.bounds.width
  34. self.window?.display() //需刷新约束才会有值,不然会变化
  35. operationBox.contentView = textPopView
  36. congfigFontPopUI()
  37. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightLeft")
  38. fontAlightButton.reloadData()
  39. break
  40. case .multpleImageEdit:
  41. imagePopView.layoutSubtreeIfNeeded()
  42. congfigMultpleImageUI()
  43. operationWidthConstraint.constant = imagePopView.bounds.width
  44. self.window?.display() //需刷新约束才会有值,不然会变化
  45. operationBox.contentView = imagePopView
  46. break
  47. case .multpleImageAndText:
  48. alightView.layoutSubtreeIfNeeded()
  49. operationWidthConstraint.constant = alightView.bounds.width
  50. self.window?.display() //需刷新约束才会有值,不然会变化
  51. operationBox.contentView = alightView
  52. break
  53. case .cropImage:
  54. cropPopView.layoutSubtreeIfNeeded()
  55. rightOffsetConstraint.constant = 0
  56. paneBox.isHidden = true
  57. operationWidthConstraint.constant = cropPopView.bounds.width
  58. self.window?.display() //需刷新约束才会有值,不然会变化
  59. operationBox.contentView = cropPopView
  60. break
  61. case .editNone:
  62. break
  63. }
  64. }
  65. }
  66. public var isOpenPane = false {
  67. didSet {
  68. if isOpenPane == true {
  69. paneSelectorItem.properties.state = .pressed
  70. } else {
  71. paneSelectorItem.properties.state = .normal
  72. }
  73. paneSelectorItem.reloadData()
  74. }
  75. }
  76. public var editContentPopMode:KMNEditContentPopMode = KMNEditContentPopMode(currentEditAreas: []) {
  77. didSet {
  78. let editPopType = editContentPopMode.popType
  79. editType = editPopType
  80. if(editType == .signTextEdit || editType == .multpleTextEdit) {
  81. let textEditAreas = listView?.km_editingTextAreas()
  82. let oldColor:NSColor? = fontColor
  83. let firstTextEditArea = textEditAreas?.first
  84. let firstColor = listView?.editingSelectionFontColor(with: firstTextEditArea)
  85. var newColor:NSColor? = firstColor
  86. for textEditArea in textEditAreas ?? [] {
  87. if firstTextEditArea != textEditArea {
  88. let color = listView?.editingSelectionFontColor(with: firstTextEditArea)
  89. if CPDFListView.isTheSameColor(color, anotherColor: firstColor) == false{
  90. newColor = nil
  91. break
  92. }
  93. }
  94. }
  95. if !CPDFListView.isTheSameColor(newColor, anotherColor: oldColor) {
  96. fontColor = newColor
  97. }
  98. let oldBold:Bool = isBold
  99. let newBolds:[Bool] = listView?.km_editTextAreasFontBolds(textEditAreas ?? []) ?? []
  100. var newBold = true
  101. for i in 0 ..< newBolds.count {
  102. let boldV = newBolds[i]
  103. if boldV == false {
  104. newBold = false
  105. break
  106. }
  107. }
  108. if oldBold != newBold {
  109. isBold = newBold
  110. }
  111. let oldItalic:Bool = isItalic
  112. let newItalics:[Bool] = listView?.km_editTextAreasFontItalics(textEditAreas ?? []) ?? []
  113. var newItalic = true
  114. for i in 0 ..< newItalics.count {
  115. let boldV = newItalics[i]
  116. if boldV == false {
  117. newItalic = false
  118. break
  119. }
  120. }
  121. if oldItalic != newItalic {
  122. isItalic = newItalic
  123. }
  124. let oldStrikeoutLine:Bool = isStrikeoutLine
  125. let newStrikeoutLines:[Bool] = listView?.km_editTextAreasFontStrikeout(textEditAreas ?? []) ?? []
  126. var newStrikeoutLine = true
  127. for i in 0 ..< newStrikeoutLines.count {
  128. let boldV = newStrikeoutLines[i]
  129. if boldV == false {
  130. newStrikeoutLine = false
  131. break
  132. }
  133. }
  134. if oldStrikeoutLine != newStrikeoutLine {
  135. isStrikeoutLine = newStrikeoutLine
  136. }
  137. let oldUnderLine:Bool = isUnderLine
  138. let newUnderLines:[Bool] = listView?.km_editTextAreasFontUnder(textEditAreas ?? []) ?? []
  139. var newUnderLine = true
  140. for i in 0 ..< newStrikeoutLines.count {
  141. let boldV = newUnderLines[i]
  142. if boldV == false {
  143. newUnderLine = false
  144. break
  145. }
  146. }
  147. if oldUnderLine != newUnderLine {
  148. isUnderLine = newUnderLine
  149. }
  150. let alights = listView?.km_editTextAreasTextAlignments(textEditAreas ?? []) ?? []
  151. var newAlignment = alights.first ?? .left
  152. let oldAlignment :NSTextAlignment = fontAlight
  153. for i in 0 ..< alights.count {
  154. let alignmentV = alights[i]
  155. if oldAlignment != alignmentV {
  156. newAlignment = .left
  157. break
  158. }
  159. }
  160. if oldAlignment != newAlignment {
  161. fontAlight = newAlignment
  162. }
  163. let fonts = listView?.km_editTextAreasComPDFFonts(textEditAreas ?? []) ?? []
  164. var newFont:CPDFFont? = fonts.first
  165. for i in 0 ..< fonts.count {
  166. let fontV = fonts[i]
  167. if i != 0 && (fontV.familyName != compdfFont?.familyName || fontV.styleName != compdfFont?.styleName) {
  168. newFont = nil
  169. break
  170. }
  171. }
  172. compdfFont = newFont
  173. }
  174. }
  175. }
  176. private var fontColor:NSColor? {
  177. didSet {
  178. fontColorItem.properties?.color = fontColor
  179. fontColorItem.reloadData()
  180. }
  181. }
  182. private var compdfFont:CPDFFont?{
  183. didSet {
  184. if(compdfFont != nil) {
  185. let styleName = compdfFont!.styleName
  186. if(styleName?.isEmpty == true) {
  187. fontNameSelect.properties.text = compdfFont!.familyName
  188. } else {
  189. fontNameSelect.properties.text = compdfFont!.familyName + "-" + (compdfFont!.styleName ?? "")
  190. }
  191. } else {
  192. fontNameSelect.properties.text = "-"
  193. }
  194. fontNameSelect.reloadData()
  195. }
  196. }
  197. private var fontAlight:NSTextAlignment = .left {
  198. didSet {
  199. if fontAlight == .center {
  200. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightCenter")
  201. } else if fontAlight == .right {
  202. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightRight")
  203. } else if fontAlight == .justified {
  204. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightJus")
  205. } else {
  206. fontAlightButton.properties.icon = NSImage(named: "KMNImageNameListViewPopAlightLeft")
  207. }
  208. fontAlightButton.reloadData()
  209. }
  210. }
  211. private var objectAlign:ObjectAlignType = .alightLeft {
  212. didSet {
  213. var zeroRect = NSRect.null
  214. var highestRect = NSZeroRect
  215. var widthestRect = NSZeroRect
  216. let objects = editContentPopMode.editAreas
  217. let fristObject : CPDFEditArea = objects.first ?? CPDFEditArea()
  218. var leftestRect = fristObject.bounds
  219. var rightestRect = fristObject.bounds
  220. var topestRect = fristObject.bounds
  221. var bottomestRect = fristObject.bounds
  222. var leftestObject : CPDFEditArea = fristObject
  223. var rightestObject : CPDFEditArea = fristObject
  224. var topestObject : CPDFEditArea = fristObject
  225. var bottomestObject: CPDFEditArea = fristObject
  226. var totalWidth = 0.0
  227. var totalHeight = 0.0
  228. for i in 0 ..< objects.count {
  229. let annotation : CPDFEditArea = objects[i]
  230. zeroRect = zeroRect.union(annotation.bounds)
  231. totalWidth = totalWidth + annotation.bounds.width
  232. totalHeight = totalHeight + annotation.bounds.height
  233. if annotation.bounds.height > highestRect.height {
  234. highestRect = annotation.bounds
  235. }
  236. if annotation.bounds.width > widthestRect.width {
  237. widthestRect = annotation.bounds
  238. }
  239. if leftestRect.minX > annotation.bounds.minX {
  240. leftestRect = annotation.bounds
  241. leftestObject = annotation
  242. }
  243. if annotation.bounds.maxX > rightestRect.maxX {
  244. rightestRect = annotation.bounds
  245. rightestObject = annotation
  246. }
  247. if annotation.bounds.maxY > topestRect.maxY {
  248. topestRect = annotation.bounds
  249. topestObject = annotation
  250. }
  251. if bottomestRect.minY > annotation.bounds.minY {
  252. bottomestRect = annotation.bounds
  253. bottomestObject = annotation
  254. }
  255. }
  256. var resultAreasArray: [CPDFEditArea] = []
  257. var newBoundsArray: [String] = []
  258. switch objectAlign {
  259. case .alightLeft :
  260. for i in 0 ..< objects.count {
  261. let object = objects[i]
  262. var bounds = object.bounds
  263. bounds.origin.x = zeroRect.origin.x
  264. newBoundsArray.append(NSStringFromRect(bounds))
  265. }
  266. resultAreasArray = objects
  267. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightLeft")
  268. break
  269. case .alightRight:
  270. for i in 0 ..< objects.count {
  271. let object = objects[i]
  272. var bounds = object.bounds
  273. bounds.origin.x = zeroRect.maxX - bounds.size.width
  274. newBoundsArray.append(NSStringFromRect(bounds))
  275. }
  276. resultAreasArray = objects
  277. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightRight")
  278. break
  279. case .alightTop:
  280. for i in 0 ..< objects.count {
  281. let object = objects[i]
  282. var bounds = object.bounds
  283. bounds.origin.y = zeroRect.maxY - bounds.size.height
  284. newBoundsArray.append(NSStringFromRect(bounds))
  285. }
  286. resultAreasArray = objects
  287. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightTop")
  288. break
  289. case .alightVer:
  290. for i in 0 ..< objects.count {
  291. let object = objects[i]
  292. var bounds = object.bounds
  293. bounds.origin.x = widthestRect.midX - bounds.width/2
  294. newBoundsArray.append(NSStringFromRect(bounds))
  295. }
  296. resultAreasArray = objects
  297. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightVer")
  298. break
  299. case .alightHor:
  300. for i in 0 ..< objects.count {
  301. let object = objects[i]
  302. var bounds = object.bounds
  303. bounds.origin.y = highestRect.midY - bounds.height/2
  304. newBoundsArray.append(NSStringFromRect(bounds))
  305. }
  306. resultAreasArray = objects
  307. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightHor")
  308. break
  309. case .alightBottom:
  310. for i in 0 ..< objects.count {
  311. let object = objects[i]
  312. var bounds = object.bounds
  313. bounds.origin.y = zeroRect.minY
  314. newBoundsArray.append(NSStringFromRect(bounds))
  315. }
  316. resultAreasArray = objects
  317. alightButton.properties.icon = NSImage(named: "KMNImageNameObjectPopAlightBottom")
  318. break
  319. case .averageVer:
  320. let middleGap = zeroRect.height - topestRect.height - bottomestRect.height
  321. let otherAreasTotalHeight = totalHeight - topestRect.height - bottomestRect.height
  322. let gap = (middleGap - otherAreasTotalHeight)/CGFloat(objects.count - 1)
  323. var areasCopyArray : [CPDFEditArea] = objects
  324. areasCopyArray.sorted(by: { obj1, obj2 in
  325. let area1 = obj1
  326. let area2 = obj2
  327. if area1.bounds.origin.x < area2.bounds.origin.x {
  328. return true
  329. } else {
  330. return false
  331. }
  332. })
  333. if let index = areasCopyArray.firstIndex(of: topestObject) {
  334. areasCopyArray.remove(at: index)
  335. }
  336. if let index = areasCopyArray.firstIndex(of: bottomestObject) {
  337. areasCopyArray.remove(at: index)
  338. }
  339. var bottomStartY = bottomestRect.maxY + gap
  340. for i in 0 ..< areasCopyArray.count {
  341. let areas = areasCopyArray[i]
  342. var bounds = areas.bounds
  343. bounds.origin.y = bottomStartY
  344. newBoundsArray.append(NSStringFromRect(bounds))
  345. bottomStartY = bottomStartY + bounds.height + gap
  346. }
  347. resultAreasArray = areasCopyArray
  348. alightButton.properties.icon = NSImage(named: "KMNImageNameObjecAlignAverageVer")
  349. break
  350. case .averageHor:
  351. let middleGap = zeroRect.width - leftestRect.width - rightestRect.width
  352. let otherAreasTotalWidth = totalWidth - leftestRect.width - rightestRect.width
  353. let gap = (middleGap - otherAreasTotalWidth)/CGFloat(objects.count - 1)
  354. var areasCopyArray : [CPDFEditArea] = objects
  355. areasCopyArray.sorted(by: { obj1, obj2 in
  356. let area1 = obj1
  357. let area2 = obj2
  358. if area1.bounds.origin.x < area2.bounds.origin.x {
  359. return true
  360. } else {
  361. return false
  362. }
  363. })
  364. if let index = areasCopyArray.firstIndex(of: leftestObject) {
  365. areasCopyArray.remove(at: index)
  366. }
  367. if let index = areasCopyArray.firstIndex(of: rightestObject) {
  368. areasCopyArray.remove(at: index)
  369. }
  370. var leftStartX = leftestRect.maxX + gap
  371. for i in 0 ..< areasCopyArray.count {
  372. let areas = areasCopyArray[i]
  373. var bounds = areas.bounds
  374. bounds.origin.x = leftStartX
  375. newBoundsArray.append(NSStringFromRect(bounds))
  376. leftStartX = leftStartX + bounds.width + gap
  377. }
  378. resultAreasArray = areasCopyArray
  379. alightButton.properties.icon = NSImage(named: "KMNImageNameObjecAlignAverageHor")
  380. break
  381. }
  382. alightButton.reloadData()
  383. for i in 0 ..< resultAreasArray.count {
  384. let editArea : CPDFEditArea = resultAreasArray[i]
  385. listView?.setBoundsEditArea(editArea, withBounds: NSRectFromString(newBoundsArray[i]))
  386. }
  387. }
  388. }
  389. private var isBold:Bool = false {
  390. didSet {
  391. fontBoldSelectorItem.properties.state = isBold ? .normal : .pressed
  392. fontBoldSelectorItem.reloadData()
  393. }
  394. }
  395. private var isItalic:Bool = false {
  396. didSet {
  397. fontItalicSelectorItem.properties.state = isItalic ? .normal : .pressed
  398. fontItalicSelectorItem.reloadData()
  399. }
  400. }
  401. private var isStrikeoutLine:Bool = false {
  402. didSet {
  403. fontStrikeoutLineSelectorItem.properties.state = isStrikeoutLine ? .normal : .pressed
  404. fontStrikeoutLineSelectorItem.reloadData()
  405. }
  406. }
  407. private var isUnderLine:Bool = false {
  408. didSet {
  409. fontUnderLineSelectorItem.properties.state = isUnderLine ? .normal : .pressed
  410. fontUnderLineSelectorItem.reloadData()
  411. }
  412. }
  413. static let shared: KMNPopContentEditWindowController = {
  414. let windowC = KMNPopContentEditWindowController(windowNibName: "KMNPopContentEditWindowController")
  415. return windowC
  416. }()
  417. var paneCallback: PaneCallback?
  418. var updatePDFViewCallback: UpdatePDFViewCallback?
  419. @IBOutlet weak var contentBox: NSBox!
  420. @IBOutlet weak var operationBox: NSBox!
  421. @IBOutlet weak var paneBox: NSBox!
  422. @IBOutlet weak var lineBox: NSBox!
  423. @IBOutlet var paneSelectorItem: ComponentCSelectorItem!
  424. @IBOutlet weak var operationWidthConstraint: NSLayoutConstraint!
  425. @IBOutlet weak var rightOffsetConstraint: NSLayoutConstraint!
  426. @IBOutlet var textPopView: NSView!
  427. @IBOutlet var fontColorItem: ComponentCColorItem!
  428. @IBOutlet var fontNameSelect: ComponentSelect!
  429. @IBOutlet var fontBoldSelectorItem: ComponentCSelector!
  430. @IBOutlet var fontItalicSelectorItem: ComponentCSelector!
  431. @IBOutlet var fontStrikeoutLineSelectorItem: ComponentCSelector!
  432. @IBOutlet var fontUnderLineSelectorItem: ComponentCSelector!
  433. @IBOutlet var fontSizeZoomOutButton: ComponentButton!
  434. @IBOutlet var fontSizeZoomInButton: ComponentButton!
  435. @IBOutlet var fontAlightButton: ComponentButton!
  436. @IBOutlet var imagePopView: NSView!
  437. @IBOutlet var rotaLeftButton: ComponentButton!
  438. @IBOutlet var rotaRightButton: ComponentButton!
  439. @IBOutlet var horizontalMirrorButton: ComponentButton!
  440. @IBOutlet var verticalMirrorButton: ComponentButton!
  441. @IBOutlet var cropButton: ComponentButton!
  442. @IBOutlet var replaceButton: ComponentButton!
  443. @IBOutlet var extractButton: ComponentButton!
  444. @IBOutlet weak var rightConstraint: NSLayoutConstraint!
  445. @IBOutlet var alightView: NSView!
  446. @IBOutlet var alightButton: ComponentButton!
  447. @IBOutlet var cropPopView: NSView!
  448. @IBOutlet var cropSureButton: ComponentButton!
  449. @IBOutlet var cropRestButton: ComponentButton!
  450. weak var listView: CPDFListView?
  451. var fontPopover:NSPopover?
  452. var ObjectPopover:NSPopover?
  453. override func windowDidLoad() {
  454. super.windowDidLoad()
  455. }
  456. override func initContentView() {
  457. super.initContentView()
  458. paneSelectorItem.properties = ComponentCSelectorProperty(iconImage:NSImage(named: "KMNImageNameListViewPopPane"))
  459. paneSelectorItem.setTarget(self, action: #selector(paneButtonClicked(_ :)))
  460. fontBoldSelectorItem.properties = ComponentCSelectorProperty(
  461. iconImage:NSImage(named: "KMNImageNameContentBold"))
  462. fontBoldSelectorItem.setTarget(self, action: #selector(fontBoldButtonClicked(_ :)))
  463. fontItalicSelectorItem.properties = ComponentCSelectorProperty(
  464. iconImage:NSImage(named: "KMNImageNameContentItalic"))
  465. fontItalicSelectorItem.setTarget(self, action: #selector(fontItalicButtonClicked(_ :)))
  466. fontStrikeoutLineSelectorItem.properties = ComponentCSelectorProperty(
  467. iconImage:NSImage(named: "KMNImageNameContentStrikeoutLine"))
  468. fontStrikeoutLineSelectorItem.setTarget(self, action: #selector(fontStrikeoutLineButtonClicked(_ :)))
  469. fontUnderLineSelectorItem.properties = ComponentCSelectorProperty(iconImage:NSImage(named: "KMNImageNameContentUnderLine"))
  470. fontUnderLineSelectorItem.setTarget(self, action: #selector(fontUnderLineButtonClicked(_ :)))
  471. fontSizeZoomOutButton.properties = ComponentButtonProperty(type: .text_gray,
  472. size: .s,
  473. state: .normal,
  474. onlyIcon: true,
  475. icon:NSImage(named: "KMNImageNameListViewPopFontSizeZoomOut"))
  476. fontSizeZoomOutButton.setTarget(self, action: #selector(fontSizeZoomOutButtonClicked(_ :)))
  477. fontSizeZoomInButton.properties = ComponentButtonProperty(type: .text_gray,
  478. size: .s,
  479. state: .normal,
  480. onlyIcon: true,
  481. icon:NSImage(named: "KMNImageNameListViewPopFontSizeZoomIn"))
  482. fontSizeZoomInButton.setTarget(self, action: #selector(fontSizeZoomInButtonClicked(_ :)))
  483. fontColorItem.properties = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: .clear)
  484. fontColorItem.delegate = self
  485. fontAlightButton.properties = ComponentButtonProperty(type: .text_gray,
  486. size: .s,
  487. state: .normal,
  488. onlyIcon: true,
  489. icon:NSImage(named: "KMNImageNameListViewPopAlightLeft"))
  490. fontAlightButton.setTarget(self, action: #selector(fontAlightButtonClicked(_ :)))
  491. rotaLeftButton.properties = ComponentButtonProperty(type: .text_gray,
  492. size: .s,
  493. state: .normal,
  494. onlyIcon: true,
  495. icon:NSImage(named: "KMNImageNameContentRotateLeft"))
  496. rotaLeftButton.setTarget(self, action: #selector(rotateLeftButtonClicked(_ :)))
  497. rotaRightButton.properties = ComponentButtonProperty(type: .text_gray,
  498. size: .s,
  499. state: .normal,
  500. onlyIcon: true,
  501. icon:NSImage(named: "KMNImageNameContentRotateRight"))
  502. rotaRightButton.setTarget(self, action: #selector(rotateRightButtonClicked(_ :)))
  503. horizontalMirrorButton.properties = ComponentButtonProperty(type: .text_gray,
  504. size: .s,
  505. state: .normal,
  506. onlyIcon: true,
  507. icon:NSImage(named: "KMNImageNameContentHorMirr"))
  508. horizontalMirrorButton.setTarget(self, action: #selector(horizontalMirrorButtonClicked(_ :)))
  509. verticalMirrorButton.properties = ComponentButtonProperty(type: .text_gray,
  510. size: .s,
  511. state: .normal,
  512. onlyIcon: true,
  513. icon:NSImage(named: "KMNImageNameContentVerMirr"))
  514. verticalMirrorButton.setTarget(self, action: #selector(verticalMirrorButtonClicked(_ :)))
  515. alightButton.properties = ComponentButtonProperty(type: .text_gray,
  516. size: .s,
  517. state: .normal,
  518. onlyIcon: true,
  519. icon:NSImage(named: "KMNImageNameObjectPopAlightLeft"))
  520. alightButton.setTarget(self, action: #selector(alightButtonClicked(_ :)))
  521. cropRestButton.properties = ComponentButtonProperty(type: .text_gray,
  522. size: .s,
  523. state: .normal,
  524. onlyIcon: true,
  525. icon:NSImage(named: "KMNImageNameContentCropRest"),keepPressState: false)
  526. cropRestButton.setTarget(self, action: #selector(cropRestClicked(_ :)))
  527. cropSureButton.properties = ComponentButtonProperty(type: .text_gray,
  528. size: .s,
  529. state: .normal,
  530. onlyIcon: true,
  531. icon:NSImage(named: "KMNImageNameContentCropSure"),keepPressState: false)
  532. cropSureButton.setTarget(self, action: #selector(cropSureClicked(_ :)))
  533. }
  534. override func updateUIThemeColor() {
  535. super.updateUIThemeColor()
  536. lineBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/divider")
  537. contentBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/popup")
  538. contentBox.borderColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/3-default")
  539. }
  540. override func updateUILanguage() {
  541. super.updateUILanguage()
  542. }
  543. //MARK: - Public
  544. public func updateFrame(listView:CPDFListView) {
  545. let editingAreas = listView.km_EditingAreas()
  546. let page = editingAreas.first?.page
  547. let windowFram = listView.window?.frame ?? CGRectZero
  548. if(page != nil) {
  549. let pageRect = listView.selectionMultipleBounds(withEditArea: editingAreas)
  550. let positioningRect = listView.convert(pageRect, from: page!)
  551. let view: NSView? = nil
  552. let position = listView.convert(positioningRect, to: view)
  553. var positionNew = position.origin
  554. positionNew.x += windowFram.origin.x + position.width/2
  555. positionNew.y += windowFram.origin.y + position.height
  556. var positionRect = self.window?.frame ?? CGRectZero
  557. positionRect.origin.x = positionNew.x - positionRect.width/2
  558. positionRect.origin.y = positionNew.y + popOffSet + CGFloat(truncating: listView.editingConfig().editAreaMargin)
  559. self.window?.setFrame(positionRect, display: true)
  560. }
  561. }
  562. //MARK: - private
  563. private func congfigFontPopUI() {
  564. fontNameSelect.properties = ComponentSelectProperties(size: .s,
  565. state: .normal,
  566. isDisabled: false,
  567. isError: false,
  568. leftIcon: false,
  569. placeholder: nil,
  570. errorText: nil,
  571. creatable: false,
  572. text: NSLocalizedString("", comment: ""))
  573. fontNameSelect.delegate = self
  574. var menuItemArr: [ComponentMenuitemProperty] = []
  575. for familyName in CPDFFont.familyNames {
  576. let fontNames = CPDFFont.fontNames(forFamilyName: familyName)
  577. let itemProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  578. itemSelected: false,
  579. isDisabled: false,
  580. keyEquivalent: nil,
  581. text: familyName)
  582. var subMenuItemArr: [ComponentMenuitemProperty] = []
  583. for fontName in fontNames {
  584. let subItemProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  585. itemSelected: false,
  586. isDisabled: false,
  587. keyEquivalent: nil,
  588. text: fontName)
  589. subMenuItemArr.append(subItemProperty)
  590. }
  591. itemProperty.subPropertys = subMenuItemArr
  592. menuItemArr.append(itemProperty)
  593. }
  594. fontNameSelect.updateMenuItemsArr(menuItemArr)
  595. }
  596. private func congfigSignImageUI() {
  597. rightConstraint.constant = 36
  598. imagePopView.display()
  599. cropButton.properties = ComponentButtonProperty(type: .text_gray,
  600. size: .s,
  601. state: .normal,
  602. onlyIcon: true,
  603. icon:NSImage(named: "KMNImageNameContentCrop"))
  604. cropButton.setTarget(self, action: #selector(cropImageButtonClicked(_ :)))
  605. replaceButton.properties = ComponentButtonProperty(type: .text_gray,
  606. size: .s,
  607. state: .normal,
  608. onlyIcon: true,
  609. icon:NSImage(named: "KMNImageNameContentReplace"))
  610. replaceButton.setTarget(self, action: #selector(replaceImageButtonClicked(_ :)))
  611. extractButton.properties = ComponentButtonProperty(type: .text_gray,
  612. size: .s,
  613. state: .normal,
  614. onlyIcon: true,
  615. icon:NSImage(named: "KMNImageNameContentExtract"))
  616. extractButton.setTarget(self, action: #selector(extractImageButtonClicked(_ :)))
  617. extractButton.isHidden = false
  618. }
  619. private func congfigMultpleImageUI() {
  620. rightConstraint.constant = 0
  621. imagePopView.display()
  622. cropButton.properties = ComponentButtonProperty(type: .text_gray,
  623. size: .s,
  624. state: .normal,
  625. onlyIcon: true,
  626. icon:NSImage(named: "KMNImageNameContentExtract"))
  627. cropButton.setTarget(self, action: #selector(extractImageButtonClicked(_ :)))
  628. replaceButton.properties = ComponentButtonProperty(type: .text_gray,
  629. size: .s,
  630. state: .normal,
  631. onlyIcon: true,
  632. icon:NSImage(named: "KMNImageNameContentReplace"))
  633. replaceButton.setTarget(self, action: #selector(alightButtonClicked(_ :)))
  634. extractButton.isHidden = true
  635. }
  636. //MARK: - Action
  637. @objc func paneButtonClicked(_ sender: NSView) {
  638. isOpenPane = !isOpenPane
  639. paneCallback?(isOpenPane)
  640. }
  641. @objc func fontBoldButtonClicked(_ sender: NSView) {
  642. listView?.setEditingTextarea_Bold()
  643. updatePDFViewCallback?()
  644. let textEditAreas = listView?.km_editingTextAreas()
  645. let newBolds:[Bool] = listView?.km_editTextAreasFontBolds(textEditAreas ?? []) ?? []
  646. if newBolds.first == false {
  647. fontBoldSelectorItem.properties.state = .normal
  648. fontBoldSelectorItem.reloadData()
  649. }
  650. }
  651. @objc func fontItalicButtonClicked(_ sender: NSView) {
  652. listView?.setEditingTextarea_Italic()
  653. updatePDFViewCallback?()
  654. let textEditAreas = listView?.km_editingTextAreas()
  655. let newItalics:[Bool] = listView?.km_editTextAreasFontItalics(textEditAreas ?? []) ?? []
  656. if newItalics.first == false {
  657. fontItalicSelectorItem.properties.state = .normal
  658. fontItalicSelectorItem.reloadData()
  659. }
  660. }
  661. @objc func fontUnderLineButtonClicked(_ sender: NSView) {
  662. listView?.setEditingTextarea_Under()
  663. updatePDFViewCallback?()
  664. let textEditAreas = listView?.km_editingTextAreas()
  665. let newUnders:[Bool] = listView?.km_editTextAreasFontUnder(textEditAreas ?? []) ?? []
  666. if newUnders.first == false {
  667. fontUnderLineSelectorItem.properties.state = .normal
  668. fontUnderLineSelectorItem.reloadData()
  669. }
  670. }
  671. @objc func fontStrikeoutLineButtonClicked(_ sender: NSView) {
  672. listView?.setEditingTextarea_Strikeout()
  673. updatePDFViewCallback?()
  674. let textEditAreas = listView?.km_editingTextAreas()
  675. let newStrikeouts:[Bool] = listView?.km_editTextAreasFontStrikeout(textEditAreas ?? []) ?? []
  676. if newStrikeouts.first == false {
  677. fontStrikeoutLineSelectorItem.properties.state = .normal
  678. fontStrikeoutLineSelectorItem.reloadData()
  679. }
  680. }
  681. @objc func fontSizeZoomOutButtonClicked(_ sender: NSView) {
  682. let textEditAreas = listView?.km_editingTextAreas()
  683. for i in 0 ..< (textEditAreas?.count ?? 0) {
  684. let textEditArea = textEditAreas?[i]
  685. let fontSize = listView?.editingSelectionFontSize(byRangeEdit: textEditArea) ?? 0
  686. if(fontSize > changeValue) {
  687. listView?.setEditingSelectionFontSize((fontSize - changeValue), with: textEditArea, isAutoSize: false)
  688. }
  689. }
  690. updatePDFViewCallback?()
  691. }
  692. @objc func fontSizeZoomInButtonClicked(_ sender: NSView) {
  693. let textEditAreas = listView?.km_editingTextAreas()
  694. for i in 0 ..< (textEditAreas?.count ?? 0) {
  695. let textEditArea = textEditAreas?[i]
  696. let fontSize = listView?.editingSelectionFontSize(byRangeEdit: textEditArea) ?? 0
  697. listView?.setEditingSelectionFontSize((fontSize + changeValue), with: textEditArea, isAutoSize: false)
  698. }
  699. updatePDFViewCallback?()
  700. }
  701. @objc func alightButtonClicked(_ sender: NSView) {
  702. if ObjectPopover?.isShown == true {
  703. ObjectPopover?.close()
  704. } else {
  705. let vc = KMNPopDetailsViewController(nibName: "KMNPopDetailsViewController", bundle: nil)
  706. let createFilePopover: NSPopover = NSPopover.init()
  707. createFilePopover.contentViewController = vc
  708. createFilePopover.delegate = self
  709. createFilePopover.animates = true
  710. createFilePopover.behavior = .semitransient
  711. createFilePopover.setValue(true, forKey: "shouldHideAnchor")
  712. 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)
  713. if (editContentPopMode.editAreas.count == 2) {
  714. vc.detailPopType = .doubleObjectAlight
  715. } else if (editContentPopMode.editAreas.count > 2) {
  716. vc.detailPopType = .multpleObjectAlight
  717. }
  718. vc.objectChangeAlighCallback = { [weak self] alight in
  719. self?.objectAlign = alight
  720. self?.updatePDFViewCallback?()
  721. }
  722. ObjectPopover = createFilePopover
  723. vc.objectAlignType = objectAlign
  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 = .contentEditAlight
  739. vc.fontChangeAlighCallback = { [weak self] alight in
  740. self?.listView?.setEditingTextarea_Alignment(align: .right)
  741. self?.fontAlight = alight
  742. self?.updatePDFViewCallback?()
  743. }
  744. fontPopover = createFilePopover
  745. vc.fontAlight = fontAlight
  746. }
  747. }
  748. @objc func rotateLeftButtonClicked(_ sender: NSView) {
  749. listView?.leftRotateAction()
  750. updatePDFViewCallback?()
  751. }
  752. @objc func rotateRightButtonClicked(_ sender: NSView) {
  753. listView?.rightRotateAction()
  754. updatePDFViewCallback?()
  755. }
  756. @objc func horizontalMirrorButtonClicked(_ sender: NSView) {
  757. listView?.reverseXAction()
  758. updatePDFViewCallback?()
  759. }
  760. @objc func verticalMirrorButtonClicked(_ sender: NSView) {
  761. listView?.reverseYAction()
  762. updatePDFViewCallback?()
  763. }
  764. @objc func cropImageButtonClicked(_ sender: NSView) {
  765. listView?.cropAction()
  766. editType = .cropImage
  767. }
  768. @objc func replaceImageButtonClicked(_ sender: NSView) {
  769. if let areas = listView?.km_editingImageAreas() {
  770. let panel = NSOpenPanel()
  771. panel.allowsMultipleSelection = false
  772. panel.allowedFileTypes = ["png","jpg"]
  773. panel.beginSheetModal(for: NSApp.mainWindow!) { response in
  774. if response == .OK {
  775. let openPath = panel.url?.path
  776. for area in areas {
  777. self.listView?.replace(area, imagePath: openPath!)
  778. }
  779. }
  780. }
  781. }
  782. }
  783. @objc func extractImageButtonClicked(_ sender: NSView) {
  784. //待确认导出格式样式
  785. listView?.exportEditingImageAreasAction(format: "jpg")
  786. }
  787. @objc func cropRestClicked(_ sender: NSView) {
  788. listView?.cropRestAction()
  789. }
  790. @objc func cropSureClicked(_ sender: NSView) {
  791. listView?.cropComfirmAction()
  792. }
  793. @objc func fontColorChange(_ sender: Any) {
  794. if let color = (sender as? NSColorPanel)?.color {
  795. listView?.changeEditingTextarea_Color(color: color)
  796. updatePDFViewCallback?()
  797. }
  798. }
  799. }
  800. //MARK: - ComponentCColorDelegate
  801. extension KMNPopContentEditWindowController: ComponentCColorDelegate {
  802. func componentCColorDidChooseColor(_ view: NSView, _ color: NSColor?) {
  803. if (view == fontColorItem) {
  804. fontColorItem.properties?.state = .normal
  805. fontColorItem.reloadData()
  806. let colorPanel = NSColorPanel.shared
  807. colorPanel.setTarget(self)
  808. colorPanel.showsAlpha = false
  809. colorPanel.setAction(#selector(self.fontColorChange(_:)))
  810. colorPanel.orderFront(nil)
  811. }
  812. }
  813. }
  814. //MARK: - ComponentSelectDelegate
  815. extension KMNPopContentEditWindowController: ComponentSelectDelegate {
  816. func componentSelectDidSelect(view: ComponentSelect?, menuItemProperty: ComponentMenuitemProperty?) {
  817. if(view == fontNameSelect) {
  818. let familyName = fontNameSelect.properties.text ?? "Helvetica"
  819. let styles = CPDFFont.fontNames(forFamilyName: familyName)
  820. compdfFont = CPDFFont(familyName: familyName, fontStyle: styles.first ?? "")
  821. listView?.setEditingTextarea_font(font: compdfFont ?? CPDFFont(familyName: "Helvetica", fontStyle: ""))
  822. } else { //字体样式
  823. compdfFont = CPDFFont(familyName: compdfFont?.familyName ?? "Helvetica", fontStyle: menuItemProperty?.text ?? "")
  824. listView?.setEditingTextarea_font(font: compdfFont ?? CPDFFont(familyName: "Helvetica", fontStyle: ""))
  825. }
  826. }
  827. }
  828. //MARK: - ComponentSelectDelegate
  829. extension KMNPopContentEditWindowController: NSPopoverDelegate {
  830. func popoverWillClose(_ notification: Notification) {
  831. if fontPopover == (notification.object as? NSPopover) {
  832. if(fontAlightButton.properties.state == .pressed) {
  833. fontAlightButton.properties.state = .normal
  834. fontAlightButton.reloadData()
  835. }
  836. } else if ObjectPopover == (notification.object as? NSPopover) {
  837. if(alightButton.properties.state == .pressed) {
  838. alightButton.properties.state = .normal
  839. alightButton.reloadData()
  840. }
  841. }
  842. }
  843. }