KMLineController.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. //
  2. // KMLineController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by Niehaoyu on 2024/11/26.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. class KMLineController: NSViewController {
  10. //Color
  11. @IBOutlet var colorBGView: NSView!
  12. @IBOutlet var colorLabel: NSTextField!
  13. @IBOutlet var colorGroup: ComponentCColorGroup!
  14. @IBOutlet var colorSlider: ComponentSlider!
  15. @IBOutlet var colorOpacitySelect: ComponentSelect!
  16. //Line
  17. @IBOutlet var lineBGView: NSView!
  18. @IBOutlet var lineLabel: NSTextField!
  19. @IBOutlet var lineTypeSelector: ComponentCSelectorGroup!
  20. @IBOutlet var lineWidthSlider: ComponentSlider!
  21. @IBOutlet var lineWidthSelect: ComponentSelect!
  22. @IBOutlet var linedashInfoView: NSView!
  23. @IBOutlet var lineDashSlider: ComponentSlider!
  24. @IBOutlet var lineDashSelect: ComponentSelect!
  25. private let solidProperty = ComponentCSelectorProperty.init(size: .s, state: .normal, text: "", iconImage: NSImage(named: "lineStyle_solid"))
  26. private let dashProperty = ComponentCSelectorProperty.init(size: .s, state: .normal, text: "", iconImage: NSImage(named: "lineStyle_dash"))
  27. private var annotations: [CPDFLineAnnotation] = []
  28. var pdfView: CPDFListView?
  29. //MARK: - func
  30. override func viewDidAppear() {
  31. super.viewDidAppear()
  32. colorSlider.reloadData()
  33. lineWidthSlider.reloadData()
  34. lineDashSlider.reloadData()
  35. }
  36. override func viewDidLoad() {
  37. super.viewDidLoad()
  38. // Do view setup here.
  39. setupProperty()
  40. }
  41. func setupProperty() {
  42. //Color
  43. colorLabel.stringValue = KMLocalizedString("Color")
  44. colorLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
  45. colorLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
  46. let colorAProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMPDFWatermarkData.watermarkDefaultColors()[0])
  47. let colorBProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMPDFWatermarkData.watermarkDefaultColors()[1])
  48. let colorCProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMPDFWatermarkData.watermarkDefaultColors()[2])
  49. let colorDProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMPDFWatermarkData.watermarkDefaultColors()[3])
  50. let colorEProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: true, color: KMPDFWatermarkData.watermarkDefaultColors()[4])
  51. colorGroup.setUpWithColorPropertys([colorAProperty, colorBProperty, colorCProperty, colorDProperty], customItemProperty: colorEProperty)
  52. colorGroup.delegate = self
  53. colorSlider.properties = ComponentSliderProperty(size: .m, percent: 1)
  54. colorSlider.delegate = self
  55. colorOpacitySelect.properties = ComponentSelectProperties(size: .s,
  56. state: .normal,
  57. creatable: true,
  58. text: "100%",
  59. textUnit: "%",
  60. regexString: "0123456789%")
  61. if true {
  62. var opacityItems: [ComponentMenuitemProperty] = []
  63. for string in ["25%", "50%", "75%", "100%"] {
  64. let item = ComponentMenuitemProperty(type: .normal, text: string)
  65. opacityItems.append(item)
  66. }
  67. colorOpacitySelect.updateMenuItemsArr(opacityItems)
  68. }
  69. colorOpacitySelect.delegate = self
  70. //Line
  71. lineLabel.stringValue = KMLocalizedString("Line")
  72. lineLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
  73. lineLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
  74. lineTypeSelector.updateItemProperty([solidProperty, dashProperty])
  75. lineTypeSelector.delegate = self
  76. lineWidthSlider.properties = ComponentSliderProperty(size: .m, percent: 1)
  77. lineWidthSlider.delegate = self
  78. lineWidthSelect.properties = ComponentSelectProperties(size: .s,
  79. state: .normal,
  80. creatable: true,
  81. text: "2",
  82. textUnit: " pt",
  83. regexString: "0123456789 pt")
  84. if true {
  85. var opacityItems: [ComponentMenuitemProperty] = []
  86. for string in ["1 pt", "3 pt", "6 pt", "9 pt", "12 pt", "15 pt", "18 pt"] {
  87. let item = ComponentMenuitemProperty(type: .normal, text: string)
  88. opacityItems.append(item)
  89. }
  90. lineWidthSelect.updateMenuItemsArr(opacityItems)
  91. }
  92. lineWidthSelect.delegate = self
  93. lineDashSlider.properties = ComponentSliderProperty(size: .m, percent: 1)
  94. lineDashSlider.delegate = self
  95. lineDashSelect.properties = ComponentSelectProperties(size: .s,
  96. state: .normal,
  97. creatable: true,
  98. text: "2",
  99. textUnit: " pt",
  100. regexString: "0123456789 pt")
  101. if true {
  102. var opacityItems: [ComponentMenuitemProperty] = []
  103. for string in ["1 pt", "3 pt", "6 pt", "9 pt", "12 pt", "15 pt", "18 pt"] {
  104. let item = ComponentMenuitemProperty(type: .normal, text: string)
  105. opacityItems.append(item)
  106. }
  107. lineDashSelect.updateMenuItemsArr(opacityItems)
  108. }
  109. lineDashSelect.delegate = self
  110. }
  111. func reloadData() {
  112. guard let pdfView = self.pdfView else {
  113. return
  114. }
  115. self.annotations.removeAll()
  116. let allAnnotations: [CPDFAnnotation] = pdfView.activeAnnotations as? [CPDFAnnotation] ?? []
  117. for annotation in allAnnotations {
  118. if annotation is CPDFLineAnnotation {
  119. annotations.append((annotation as! CPDFLineAnnotation))
  120. }
  121. }
  122. if annotations.count == 0 {
  123. return
  124. }
  125. guard let firstAnnotation = annotations.first else {
  126. return
  127. }
  128. if annotations.count == 1 {
  129. colorGroup.currentColor = firstAnnotation.color
  130. colorGroup.refreshUI()
  131. let opacity = firstAnnotation.opacity
  132. colorSlider.properties.percent = opacity
  133. colorSlider.reloadData()
  134. colorOpacitySelect.properties.text = String(format: "%.0f%@", opacity*100, "%")
  135. colorOpacitySelect.reloadData()
  136. let border: CPDFBorder = firstAnnotation.border
  137. dashProperty.state = .normal
  138. solidProperty.state = .normal
  139. if border.style == .dashed {
  140. dashProperty.state = .pressed
  141. } else if border.style == .solid {
  142. solidProperty.state = .pressed
  143. }
  144. lineTypeSelector.reloadData()
  145. let percent = (border.lineWidth - 1)/17
  146. lineWidthSlider.properties.percent = percent
  147. lineWidthSlider.reloadData()
  148. lineWidthSelect.properties.text = String(format: "%.0f%@", border.lineWidth, " pt")
  149. lineWidthSelect.reloadData()
  150. linedashInfoView.isHidden = true
  151. if border.style == .dashed {
  152. linedashInfoView.isHidden = false
  153. var dash = 1.0
  154. for dashPattern in border.dashPattern {
  155. if let value = dashPattern as? CGFloat {
  156. dash = value
  157. break
  158. }
  159. }
  160. let percent: CGFloat = (CGFloat(dash) - 1)/17
  161. lineDashSlider.properties.percent = percent
  162. lineDashSlider.reloadData()
  163. lineDashSelect.properties.text = String(format: "%.0f%@", CGFloat(dash), " pt")
  164. lineDashSelect.reloadData()
  165. }
  166. } else {
  167. // if true {
  168. // var multiColor: Bool = false
  169. // for annotationA in annotations {
  170. // for annotationB in annotations {
  171. // if annotationA != annotationB {
  172. // if annotationA.color != annotationB.color {
  173. // multiColor = true
  174. // break
  175. // }
  176. // }
  177. // }
  178. // if multiColor == true {
  179. // break
  180. // }
  181. // }
  182. // if multiColor == true {
  183. // colorGroup.currentColor = NSColor.clear
  184. // } else {
  185. // colorGroup.currentColor = firstAnnotation.color
  186. // }
  187. // colorGroup.refreshUI()
  188. // }
  189. //
  190. // if true {
  191. // var multiOpacity: Bool = false
  192. // for annotationA in annotations {
  193. // for annotationB in annotations {
  194. // if annotationA != annotationB {
  195. // if annotationA.opacity != annotationB.opacity {
  196. // multiOpacity = true
  197. // break
  198. // }
  199. // }
  200. // }
  201. // if multiOpacity == true {
  202. // break
  203. // }
  204. // }
  205. //
  206. // if multiOpacity {
  207. // colorSlider.properties.percent = 0
  208. // colorSlider.reloadData()
  209. //
  210. // colorOpacitySelect.resetText("-")
  211. // } else {
  212. // let opacity = firstAnnotation.opacity
  213. //
  214. // colorSlider.properties.percent = opacity
  215. // colorSlider.reloadData()
  216. //
  217. // colorOpacitySelect.properties.text = String(format: "%.0f%@", opacity*100, "%")
  218. // colorOpacitySelect.reloadData()
  219. // }
  220. // }
  221. //
  222. // if true {
  223. // var multiStyle: Bool = false
  224. // for annotationA in annotations {
  225. // for annotationB in annotations {
  226. // if annotationA != annotationB {
  227. // if annotationA.borderStyle() != annotationB.borderStyle() {
  228. // multiStyle = true
  229. // break
  230. // }
  231. // }
  232. // }
  233. // if multiStyle == true {
  234. // break
  235. // }
  236. // }
  237. //
  238. // linedashInfoView.isHidden = true
  239. // if multiStyle {
  240. // dashProperty.state = .normal
  241. // solidProperty.state = .normal
  242. //
  243. // lineTypeSelector.reloadData()
  244. // } else {
  245. // let style = firstAnnotation.border.style
  246. // dashProperty.state = .normal
  247. // solidProperty.state = .normal
  248. // if style == .dashed {
  249. // dashProperty.state = .pressed
  250. // } else if style == .solid {
  251. // solidProperty.state = .pressed
  252. // }
  253. // lineTypeSelector.reloadData()
  254. //
  255. // if style == .dashed {
  256. // linedashInfoView.isHidden = false
  257. // }
  258. // }
  259. // }
  260. //
  261. // if true {
  262. // var multiLineWidth: Bool = false
  263. // for annotationA in annotations {
  264. // for annotationB in annotations {
  265. // if annotationA != annotationB {
  266. // if annotationA.borderStyle() != annotationB.borderStyle() {
  267. // multiLineWidth = true
  268. // break
  269. // }
  270. // }
  271. // }
  272. // if multiLineWidth == true {
  273. // break
  274. // }
  275. // }
  276. // if multiLineWidth {
  277. // lineWidthSlider.properties.percent = 0
  278. // lineWidthSlider.reloadData()
  279. //
  280. // lineWidthSelect.resetText("-")
  281. // } else {
  282. // let border: CPDFBorder = firstAnnotation.border
  283. //
  284. // let percent = (border.lineWidth - 1)/17
  285. // lineWidthSlider.properties.percent = percent
  286. // lineWidthSlider.reloadData()
  287. //
  288. // lineWidthSelect.properties.text = String(format: "%.0f%@", border.lineWidth, " pt")
  289. // lineWidthSelect.reloadData()
  290. // }
  291. // }
  292. //
  293. // if true {
  294. // var multiLineDash: Bool = false
  295. // for annotationA in annotations {
  296. // var dashA = 1.0
  297. // for dashPattern in annotationA.border.dashPattern {
  298. // if let value = dashPattern as? CGFloat {
  299. // dashA = value
  300. // break
  301. // }
  302. // }
  303. // for annotationB in annotations {
  304. // if annotationA != annotationB {
  305. // var dashB = 1.0
  306. // for dashPattern in annotationB.border.dashPattern {
  307. // if let value = dashPattern as? CGFloat {
  308. // dashB = value
  309. // break
  310. // }
  311. // }
  312. // if dashA != dashB {
  313. // multiLineDash = true
  314. // break
  315. // }
  316. // }
  317. // }
  318. // if multiLineDash == true {
  319. // break
  320. // }
  321. // }
  322. // if multiLineDash {
  323. // lineDashSlider.properties.percent = 0
  324. // lineDashSlider.reloadData()
  325. //
  326. // lineDashSelect.resetText("-")
  327. // } else {
  328. // var dashA = 1.0
  329. // for dashPattern in firstAnnotation.border.dashPattern {
  330. // if let value = dashPattern as? CGFloat {
  331. // dashA = value
  332. // break
  333. // }
  334. // }
  335. //
  336. // let percent = (dashA - 1)/17
  337. // lineDashSlider.properties.percent = percent
  338. // lineDashSlider.reloadData()
  339. //
  340. // lineDashSelect.properties.text = String(format: "%.0f%@", dashA, " pt")
  341. // lineDashSelect.reloadData()
  342. // }
  343. // }
  344. }
  345. }
  346. //MARK: - Mouse
  347. override func mouseDown(with event: NSEvent) {
  348. super.mouseDown(with: event)
  349. view.window?.makeFirstResponder(nil)
  350. }
  351. }
  352. //MARK: - ComponentCColorDelegate
  353. extension KMLineController: ComponentCColorDelegate {
  354. func componentCColorDidChooseColor(_ view: NSView, _ color: NSColor?) {
  355. for annotation in self.annotations {
  356. annotation.updateColor(color, withPDFView: pdfView)
  357. }
  358. reloadData()
  359. }
  360. }
  361. //MARK: - ComponentSliderDelegate
  362. extension KMLineController: ComponentSliderDelegate {
  363. func componentSliderDidUpdate(_ view: ComponentSlider) {
  364. if view == colorSlider {
  365. let percent = view.properties.percent
  366. for annotation in self.annotations {
  367. annotation.updateOpacity(percent, withPDFView: pdfView)
  368. }
  369. } else if view == lineWidthSlider {
  370. let percent = view.properties.percent * 17 + 1
  371. for annotation in self.annotations {
  372. annotation.updateLineWidth(percent, withPDFView: pdfView)
  373. }
  374. } else if view == lineDashSlider {
  375. let percent = view.properties.percent * 17 + 1
  376. for annotation in self.annotations {
  377. annotation.updateDashPattern(percent, withPDFView: pdfView)
  378. }
  379. }
  380. reloadData()
  381. }
  382. }
  383. //MARK: - ComponentSelectDelegate
  384. extension KMLineController: ComponentSelectDelegate {
  385. func componentSelectTextDidEndEditing(_ view: ComponentSelect, removeUnit text: String?) {
  386. if let result = text {
  387. if view == colorOpacitySelect {
  388. let opacity = max(0, min(1, result.stringToCGFloat()/100))
  389. for annotation in self.annotations {
  390. annotation.updateOpacity(opacity, withPDFView: pdfView)
  391. }
  392. } else if view == lineWidthSelect {
  393. var value = result.stringToCGFloat()
  394. if value > 18 {
  395. value = 18
  396. } else if value < 1 {
  397. value = 1
  398. }
  399. for annotation in self.annotations {
  400. annotation.updateLineWidth(value, withPDFView: pdfView)
  401. }
  402. } else if view == lineDashSelect {
  403. var value = result.stringToCGFloat()
  404. if value > 18 {
  405. value = 18
  406. } else if value < 1 {
  407. value = 1
  408. }
  409. for annotation in self.annotations {
  410. annotation.updateDashPattern(value, withPDFView: pdfView)
  411. }
  412. }
  413. reloadData()
  414. }
  415. }
  416. func componentSelectDidSelect(view: ComponentSelect?, menuItemProperty: ComponentMenuitemProperty?) {
  417. if var result = menuItemProperty?.text {
  418. if let textUnit = view?.properties.textUnit {
  419. result = result.stringByDeleteCharString(textUnit)
  420. }
  421. if view == colorOpacitySelect {
  422. let opacity = max(0, min(1, result.stringToCGFloat()/100))
  423. for annotation in self.annotations {
  424. annotation.updateOpacity(opacity, withPDFView: pdfView)
  425. }
  426. } else if view == lineWidthSelect {
  427. var value = result.stringToCGFloat()
  428. if value > 18 {
  429. value = 18
  430. } else if value < 1 {
  431. value = 1
  432. }
  433. for annotation in self.annotations {
  434. annotation.updateLineWidth(value, withPDFView: pdfView)
  435. }
  436. } else if view == lineDashSelect {
  437. var value = result.stringToCGFloat()
  438. if value > 18 {
  439. value = 18
  440. } else if value < 1 {
  441. value = 1
  442. }
  443. for annotation in self.annotations {
  444. annotation.updateDashPattern(value, withPDFView: pdfView)
  445. }
  446. }
  447. reloadData()
  448. }
  449. }
  450. }
  451. //MARK: - ComponentCSelectorGroupDelegate
  452. extension KMLineController: ComponentCSelectorGroupDelegate {
  453. func componentCSelectorGroupDidChoose(_ view: ComponentCSelectorGroup, _ item: ComponentCSelectorItem) {
  454. if item.properties == solidProperty {
  455. for annotation in self.annotations {
  456. annotation.updateStyle(.solid, withPDFView: pdfView)
  457. }
  458. } else if item.properties == dashProperty {
  459. for annotation in self.annotations {
  460. annotation.updateStyle(.dashed, withPDFView: pdfView)
  461. }
  462. }
  463. reloadData()
  464. }
  465. }