KMOutlineEditViewController.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. //
  2. // KMOutlineEditViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lxy on 2022/11/9.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. class KMOutlineEditViewController: KMNBaseViewController {
  10. @IBOutlet var outlineNameTextView: NSTextView!
  11. @IBOutlet weak var outlineNameLabel: NSTextField!
  12. @IBOutlet weak var outlineTargetPageIndexTextField: NSTextField!
  13. @IBOutlet weak var pageButton: NSButton!
  14. @IBOutlet weak var totalPageCountLabel: NSTextField!
  15. @IBOutlet weak var outlineURLTextField: NSTextField!
  16. @IBOutlet weak var urlButton: NSButton!
  17. @IBOutlet weak var mailAddressTextField: NSTextField!
  18. @IBOutlet weak var mailButton: NSButton!
  19. @IBOutlet weak var inputScrollView: NSScrollView!
  20. @IBOutlet weak var pageBox: NSBox!
  21. @IBOutlet weak var webBox: NSBox!
  22. @IBOutlet weak var emailBox: NSBox!
  23. @IBOutlet weak var bottomBox: NSBox!
  24. @IBOutlet weak var leftButtonBox: NSBox!
  25. @IBOutlet weak var rightButtonBox: NSBox!
  26. weak var outline : CPDFOutline?
  27. weak var pdfView : CPDFView?
  28. var originalURLString : String = ""
  29. weak var originalDestination : CPDFDestination?
  30. var originalPageIndex = -1
  31. var originalLabel : String = ""
  32. var currentPageIndex : Int = 0
  33. var pageCount = 0
  34. var itemClick: KMCommonClickBlock?
  35. private lazy var inputView_: ComponentTextarea = {
  36. let view = ComponentTextarea()
  37. view.properties = ComponentTextareaProperty(size: .m, state: .pressed, isError: false, placeholderString: "", totalCount: -1, text: "", isDisabled: false)
  38. return view
  39. }()
  40. private lazy var pageRadio_: ComponentRadio = {
  41. let view = ComponentRadio()
  42. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("Page:", comment: ""), checkboxType: .normal)
  43. return view
  44. }()
  45. private lazy var pageInput_: ComponentInput = {
  46. let view = ComponentInput()
  47. let inputWithAddonProperty = ComponentInputProperty(size: .s,
  48. state: .normal,
  49. isError: false,
  50. showPrefix: false,
  51. showSuffix: false,
  52. showClear: false,
  53. isDisabled: true,
  54. placeholder: "",
  55. text: "",
  56. creatable: true)
  57. view.properties = inputWithAddonProperty
  58. return view
  59. }()
  60. private lazy var pageLabel: NSTextField = {
  61. let view = NSTextField(labelWithString: "")
  62. return view
  63. }()
  64. private lazy var webRadio_: ComponentRadio = {
  65. let view = ComponentRadio()
  66. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("Webside:", comment: ""), checkboxType: .normal)
  67. return view
  68. }()
  69. private lazy var webInput_: ComponentInput = {
  70. let view = ComponentInput()
  71. view.properties = ComponentInputProperty(size: .s, placeholder: KMLocalizedString("http://www.pdfreaderpro.com"), text: "")
  72. return view
  73. }()
  74. private lazy var emailRadio_: ComponentRadio = {
  75. let view = ComponentRadio()
  76. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("Email:", comment: ""), checkboxType: .normal)
  77. return view
  78. }()
  79. private lazy var emailInput_: ComponentInput = {
  80. let view = ComponentInput()
  81. view.properties = ComponentInputProperty(size: .s, placeholder: KMLocalizedString("support@pdfreaderpro.com"), text: "")
  82. return view
  83. }()
  84. private lazy var cancelButton_: ComponentButton = {
  85. let view = ComponentButton()
  86. view.properties = ComponentButtonProperty(type: .default_tertiary, size: .s, state: .normal, isDisable: false, onlyIcon: false, buttonText: KMLocalizedString("Cancel"), keepPressState: false)
  87. return view
  88. }()
  89. private lazy var okButton_: ComponentButton = {
  90. let view = ComponentButton()
  91. view.properties = ComponentButtonProperty(type: .primary, size: .s, state: .normal, isDisable: false, onlyIcon: false, buttonText: KMLocalizedString("Apply"), keepPressState: false)
  92. return view
  93. }()
  94. var pageRadio: ComponentRadio {
  95. get {
  96. return pageRadio_
  97. }
  98. }
  99. var pageInput: ComponentInput {
  100. get {
  101. return pageInput_
  102. }
  103. }
  104. var webRaido: ComponentRadio {
  105. get {
  106. return webRadio_
  107. }
  108. }
  109. var webInput: ComponentInput {
  110. get {
  111. return webInput_
  112. }
  113. }
  114. var emailRadio: ComponentRadio {
  115. get {
  116. return emailRadio_
  117. }
  118. }
  119. var emailInput: ComponentInput {
  120. get {
  121. return emailInput_
  122. }
  123. }
  124. convenience init(outline: CPDFOutline?, document: CPDFView?) {
  125. self.init()
  126. self.outline = outline
  127. self.pdfView = document
  128. }
  129. override func loadView() {
  130. super.loadView()
  131. // 382-48=334 64
  132. inputView_.frame = inputScrollView.contentView.bounds
  133. inputView_.autoresizingMask = [.width, .height]
  134. inputScrollView.documentView = inputView_
  135. inputView_.properties.text = outline?.label ?? ""
  136. inputView_.reloadData()
  137. pageButton.isHidden = true
  138. totalPageCountLabel.isHidden = true
  139. pageBox.borderWidth = 0
  140. pageBox.contentView?.addSubview(pageRadio_)
  141. pageBox.contentView?.addSubview(pageInput_)
  142. pageBox.contentView?.addSubview(pageLabel)
  143. pageRadio_.km_add_centerY_constraint()
  144. pageRadio_.km_add_leading_constraint()
  145. pageRadio_.km_add_width_constraint(constant: pageRadio_.properties.propertyInfo.viewWidth+8)
  146. pageRadio_.km_add_height_constraint(constant: 20)
  147. pageInput_.km_add_leading_constraint(equalTo: pageRadio_, attribute: .trailing, constant: 0)
  148. pageInput_.km_add_centerY_constraint()
  149. pageInput_.km_add_height_constraint(constant: 32)
  150. pageInput_.km_add_width_constraint(constant: 80)
  151. pageLabel.km_add_leading_constraint(equalTo: pageInput_, attribute: .trailing, constant: 8)
  152. pageLabel.km_add_centerY_constraint()
  153. pageLabel.stringValue = "/\(pageCount)"
  154. pageInput_.properties.text = "11"
  155. pageInput_.reloadData()
  156. pageRadio_.setTarget(self, action: #selector(buttonClicked_GotoAction))
  157. urlButton.isHidden = true
  158. outlineURLTextField.isHidden = true
  159. webBox.borderWidth = 0
  160. webBox.contentView?.addSubview(webRadio_)
  161. webBox.contentView?.addSubview(webInput_)
  162. webRadio_.km_add_centerY_constraint()
  163. webRadio_.km_add_leading_constraint()
  164. webRadio_.km_add_width_constraint(constant: webRadio_.properties.propertyInfo.viewWidth+8)
  165. webRadio_.km_add_height_constraint(constant: 20)
  166. webInput_.km_add_leading_constraint(equalTo: webRadio_, attribute: .trailing, constant: 0)
  167. webInput_.km_add_centerY_constraint()
  168. webInput_.km_add_height_constraint(constant: 32)
  169. webInput_.km_add_trailing_constraint()
  170. webRadio_.setTarget(self, action: #selector(buttonClicked_URLAction))
  171. mailButton.isHidden = true
  172. mailAddressTextField.isHidden = true
  173. emailBox.borderWidth = 0
  174. emailBox.contentView?.addSubview(emailRadio_)
  175. emailBox.contentView?.addSubview(emailInput_)
  176. emailRadio_.km_add_centerY_constraint()
  177. emailRadio_.km_add_leading_constraint()
  178. emailRadio_.km_add_width_constraint(constant: emailRadio_.properties.propertyInfo.viewWidth+8)
  179. emailRadio_.km_add_height_constraint(constant: 20)
  180. emailInput_.km_add_leading_constraint(equalTo: emailRadio_, attribute: .trailing, constant: 0)
  181. emailInput_.km_add_centerY_constraint()
  182. emailInput_.km_add_height_constraint(constant: 32)
  183. emailInput_.km_add_trailing_constraint()
  184. emailRadio_.setTarget(self, action: #selector(buttonClicked_MailAction))
  185. bottomBox.borderWidth = 0
  186. leftButtonBox.borderWidth = 0
  187. leftButtonBox.contentView = cancelButton_
  188. rightButtonBox.borderWidth = 0
  189. rightButtonBox.contentView = okButton_
  190. cancelButton_.setTarget(self, action: #selector(_cancelAction))
  191. okButton_.setTarget(self, action: #selector(_okAction))
  192. outlineNameLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-medium")
  193. pageLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-regular")
  194. setONButton(button: pageRadio_)
  195. enableTextField(textField: pageInput_)
  196. setDelegateAndFormatter()
  197. if let action = outline?.action {
  198. adjustUIWithAction(action: action)
  199. }
  200. }
  201. override func updateUILanguage() {
  202. super.updateUILanguage()
  203. KMMainThreadExecute {
  204. self.outlineNameLabel.stringValue = KMLocalizedString("Rename")
  205. }
  206. }
  207. override func updateUIThemeColor() {
  208. super.updateUIThemeColor()
  209. view.wantsLayer = true
  210. KMMainThreadExecute {
  211. self.view.layer?.backgroundColor = KMNColorTools.colorBg_popup().cgColor
  212. self.outlineNameLabel.textColor = KMNColorTools.colorText_1()
  213. self.pageLabel.textColor = KMNColorTools.compField_colorTextFilledNor()
  214. }
  215. }
  216. //MARK: - Private Methods
  217. private func adjustUIWithAction(action:CPDFAction!) {
  218. guard let doc = self.pdfView?.document else {
  219. return
  220. }
  221. if action == nil {
  222. pageLabel.stringValue = " \(doc.pageCount)"
  223. pageInput_.properties.text = " \(currentPageIndex + 1)"
  224. pageInput_.reloadData()
  225. } else {
  226. guard let outL = outline else {
  227. return
  228. }
  229. if action.isKind(of: CPDFURLAction.self) {
  230. var newAction : CPDFURLAction = outline?.action as! CPDFURLAction
  231. var urlString = newAction.url() ?? ""
  232. originalURLString = urlString
  233. if urlString.hasPrefix("mailto:") {
  234. setONButton(button: emailRadio_)
  235. enableTextField(textField: emailInput_)
  236. urlString = String(urlString.suffix(from: "mailto:".endIndex))
  237. emailInput_.properties.text = urlString
  238. emailInput_.reloadData()
  239. } else {
  240. setONButton(button: webRadio_)
  241. enableTextField(textField: webInput_)
  242. webInput_.properties.text = urlString
  243. webInput_.reloadData()
  244. }
  245. currentPageIndex = Int(doc.index(for: doc.page(at: UInt(pdfView?.currentPageIndex ?? 0))))
  246. } else {
  247. setONButton(button: pageRadio_)
  248. enableTextField(textField: pageInput_)
  249. currentPageIndex = Int(doc.index(for: doc.page(at: UInt(outL.destination.pageIndex))))
  250. originalDestination = outL.destination
  251. originalPageIndex = originalDestination?.pageIndex ?? -1
  252. }
  253. originalLabel = outL.label ?? ""
  254. pageLabel.stringValue = " /\(doc.pageCount)"
  255. pageInput_.properties.text = "\(self.currentPageIndex + 1)"
  256. pageInput_.reloadData()
  257. }
  258. }
  259. private func setDelegateAndFormatter () {
  260. self.outlineTargetPageIndexTextField.delegate = self
  261. self.outlineNameTextView.delegate = self
  262. var formatter = NumberFormatter()
  263. formatter.numberStyle = .none
  264. formatter.maximum = NSNumber(value: self.pdfView?.document?.pageCount ?? 0)
  265. formatter.minimum = NSNumber(value: 1)
  266. self.outlineTargetPageIndexTextField.formatter = formatter
  267. }
  268. private func setONButton(button sender: ComponentRadio) {
  269. for radio in [pageRadio_, webRadio_, emailRadio_] {
  270. if radio.isEqual(to: sender) {
  271. radio.properties.checkboxType = .selected
  272. } else {
  273. radio.properties.checkboxType = .normal
  274. }
  275. radio.reloadData()
  276. }
  277. }
  278. private func enableTextField(textField sender: ComponentInput) {
  279. for input in [pageInput_, webInput_, emailInput_] {
  280. if sender.isEqual(to: input) {
  281. input.properties.isDisabled = false
  282. input.properties.creatable = true
  283. } else {
  284. input.properties.isDisabled = true
  285. input.properties.creatable = false
  286. }
  287. input.reloadData()
  288. }
  289. }
  290. //MARK: Button Action
  291. @IBAction func buttonClicked_GotoAction(_ sender: Any) {
  292. self.setONButton(button: pageRadio_)
  293. self.enableTextField(textField: pageInput_)
  294. // self.view.window?.makeFirstResponder(self.outlineTargetPageIndexTextField)
  295. }
  296. @IBAction func buttonClicked_URLAction(_ sender: Any) {
  297. self.setONButton(button: self.webRadio_)
  298. self.enableTextField(textField: webInput_)
  299. // self.view.window?.makeFirstResponder(self.outlineURLTextField)
  300. if (self.outlineTargetPageIndexTextField.stringValue == "0" || self.outlineTargetPageIndexTextField.stringValue.lengthOfBytes(using: String.Encoding(rawValue: String.Encoding.utf16.rawValue)) < 1){
  301. self.outlineTargetPageIndexTextField.stringValue = "\(self.currentPageIndex + 1)"
  302. }
  303. }
  304. @IBAction func buttonClicked_MailAction(_ sender: Any) {
  305. self.setONButton(button: self.emailRadio_)
  306. self.enableTextField(textField: emailInput_)
  307. // self.view.window?.makeFirstResponder(self.mailAddressTextField)
  308. if (self.outlineTargetPageIndexTextField.stringValue == "0" || self.outlineTargetPageIndexTextField.stringValue.lengthOfBytes(using: String.Encoding(rawValue: String.Encoding.utf16.rawValue)) < 1){
  309. self.outlineTargetPageIndexTextField.stringValue = "\(self.currentPageIndex + 1)"
  310. }
  311. }
  312. @objc private func _cancelAction() {
  313. itemClick?(1)
  314. }
  315. @objc private func _okAction() {
  316. itemClick?(2, self)
  317. }
  318. }
  319. extension KMOutlineEditViewController : NSTextFieldDelegate,NSTextViewDelegate {
  320. func controlTextDidChange(_ obj: Notification) {
  321. if self.outlineTargetPageIndexTextField.isEqual(obj.object) {
  322. let number = NSNumber(value: Int(self.outlineTargetPageIndexTextField.stringValue) ?? 0)
  323. let string = self.outlineTargetPageIndexTextField.formatter?.string(for: number)
  324. let s = Int(string ?? "")
  325. if s != 0 {
  326. self.currentPageIndex = (s ?? 0) - 1
  327. }
  328. self.outlineTargetPageIndexTextField.stringValue = string ?? ""
  329. }
  330. }
  331. }