KMHeaderFooterManager.swift 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. import Foundation
  2. let kHeaderFooterFolderPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("headerFooter")
  3. let kHeaderFooterPlistPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("headerFooter").stringByAppendingPathComponent("headerFooter2025.plist")
  4. let KMHeaderFooterDatasUpdateNotiName = NSNotification.Name("KMHeaderFooterDatasUpdateNotiName")
  5. class KMHeaderFooterManager: NSObject {
  6. static let defaultManager = KMHeaderFooterManager()
  7. var headFooterObjects: [KMHeaderFooterModel] = []
  8. var defaultHeaderFooter: KMHeaderFooterModel = KMHeaderFooterModel()
  9. override init() {
  10. super.init()
  11. #if DEBUG
  12. print("kHeaderFooterPlistPath = \(kHeaderFooterPlistPath ?? "")")
  13. #endif
  14. if (FileManager.default.fileExists(atPath: kHeaderFooterPlistPath!)) {
  15. let dataDict = NSDictionary(contentsOfFile: kHeaderFooterPlistPath!)
  16. if (dataDict == nil) {
  17. return
  18. }
  19. for keyIndex in 0 ..< (dataDict?.allKeys.count)! {
  20. let key: String = dataDict?.allKeys[keyIndex] as! String
  21. let backgroundDict: NSDictionary = dataDict?.object(forKey: key) as! NSDictionary
  22. let model = parseDictionary(dict: backgroundDict)
  23. model.tag = key
  24. self.headFooterObjects.append(model)
  25. self.defaultHeaderFooter.name = self.fetchHeaderFooterAvailableName()
  26. }
  27. }
  28. }
  29. //MARK: - 增删改查
  30. func addHeaderFooter(_ obj: KMHeaderFooterModel) -> Bool {
  31. if (!FileManager.default.fileExists(atPath: kHeaderFooterFolderPath!)) {
  32. let create: ()? = try?FileManager.default.createDirectory(atPath: kHeaderFooterFolderPath!, withIntermediateDirectories: false)
  33. if (create == nil) {
  34. return false
  35. }
  36. }
  37. if (!FileManager.default.fileExists(atPath: kHeaderFooterPlistPath!)) {
  38. let create = try?FileManager.default.createFile(atPath: kHeaderFooterPlistPath!, contents: nil)
  39. if (create == nil) {
  40. return false
  41. }
  42. }
  43. let dict = NSDictionary(contentsOfFile: kHeaderFooterPlistPath!)
  44. var newDict:NSMutableDictionary!
  45. if (dict != nil) {
  46. newDict = NSMutableDictionary(dictionary: dict!)
  47. } else {
  48. newDict = NSMutableDictionary()
  49. }
  50. let backgroundDict = self.parseModel(model: obj)
  51. if (backgroundDict.isEmpty) {
  52. let alert = NSAlert()
  53. alert.alertStyle = .critical
  54. alert.runModal()
  55. return false
  56. }
  57. let tag = obj.tag
  58. newDict.addEntries(from: [tag : backgroundDict])
  59. let result = newDict.write(toFile: kHeaderFooterPlistPath!, atomically: true)
  60. if (result) {
  61. if (self.headFooterObjects.count < 1) {
  62. self.headFooterObjects.append(obj)
  63. } else {
  64. self.headFooterObjects.insert(obj, at: 0)
  65. }
  66. }
  67. NotificationCenter.default.post(name: KMHeaderFooterDatasUpdateNotiName, object: nil)
  68. return result
  69. }
  70. func removeHeaderFooter(_ obj: KMHeaderFooterModel) -> Bool {
  71. if (obj.tag.isEmpty) {
  72. return false
  73. }
  74. if (!FileManager.default.fileExists(atPath: kHeaderFooterPlistPath!)) {
  75. return false
  76. }
  77. let key: String = obj.tag
  78. let dictionary = NSDictionary(contentsOfFile: kHeaderFooterPlistPath!)
  79. var newDictionary: NSMutableDictionary!
  80. if (dictionary != nil) {
  81. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  82. } else {
  83. newDictionary = NSMutableDictionary()
  84. }
  85. newDictionary.removeObject(forKey: key)
  86. let result = newDictionary.write(toFile: kHeaderFooterPlistPath!, atomically: true)
  87. if (result) {
  88. if (self.headFooterObjects.contains(obj)) {
  89. self.headFooterObjects.removeObject(obj)
  90. }
  91. }
  92. NotificationCenter.default.post(name: KMHeaderFooterDatasUpdateNotiName, object: nil)
  93. return result
  94. }
  95. func removeAllHeaderFooters() -> Bool {
  96. if (!FileManager.default.fileExists(atPath: kHeaderFooterPlistPath!)) {
  97. return false
  98. }
  99. let dictionary = NSDictionary(contentsOfFile: kHeaderFooterPlistPath!)
  100. var newDictionary: NSMutableDictionary!
  101. if (dictionary != nil) {
  102. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  103. } else {
  104. newDictionary = NSMutableDictionary()
  105. }
  106. newDictionary.removeAllObjects()
  107. let result = newDictionary.write(toFile: kHeaderFooterPlistPath!, atomically: true)
  108. if (result) {
  109. self.headFooterObjects.removeAll()
  110. }
  111. NotificationCenter.default.post(name: KMHeaderFooterDatasUpdateNotiName, object: nil)
  112. return result
  113. }
  114. func updateHeaderFooter(theModel: KMHeaderFooterModel) -> Bool {
  115. var flagModel: KMHeaderFooterModel!
  116. for model in self.headFooterObjects {
  117. if (model.tag == theModel.tag) {
  118. flagModel = model
  119. break
  120. }
  121. }
  122. if (flagModel == nil) {
  123. return false
  124. }
  125. let dict = NSDictionary(contentsOfFile: kHeaderFooterPlistPath!)
  126. var newDict:NSMutableDictionary!
  127. if (dict != nil) {
  128. newDict = NSMutableDictionary(dictionary: dict!)
  129. } else {
  130. newDict = NSMutableDictionary()
  131. }
  132. let watermarkDict = self.parseModel(model: theModel)
  133. newDict.setObject(watermarkDict, forKey: flagModel.tag as NSCopying)
  134. let result = newDict.write(toFile: kHeaderFooterPlistPath!, atomically: true)
  135. if (result) {
  136. if let index = self.headFooterObjects.firstIndex(of: flagModel) {
  137. self.headFooterObjects[index] = theModel
  138. }
  139. }
  140. NotificationCenter.default.post(name: KMHeaderFooterDatasUpdateNotiName, object: nil)
  141. return result
  142. }
  143. func updateModel(_ model: KMHeaderFooterModel, with dict: NSDictionary) {
  144. model.fontName = dict.object(forKey: "fontName") as! String
  145. model.fontsize = dict.object(forKey: "fontsize") as! CGFloat
  146. if let value = dict.object(forKey: "color") {
  147. model.color = NSColor.km_init(hex: value as! String)
  148. }
  149. model.leftMargin = dict.object(forKey: "leftMargin") as! Int
  150. model.rightMargin = dict.object(forKey: "rightMargin") as! Int
  151. model.bottomMargin = dict.object(forKey: "bottomMargin") as! Int
  152. model.topMargin = dict.object(forKey: "topMargin") as! Int
  153. model.topLeftString = dict.object(forKey: "topLeftString") as! String
  154. model.topCenterString = dict.object(forKey: "topCenterString") as! String
  155. model.topRightString = dict.object(forKey: "topRightString") as! String
  156. model.bottomLeftString = dict.object(forKey: "bottomLeftString") as! String
  157. model.bottomCenterString = dict.object(forKey: "bottomCenterString") as! String
  158. model.bottomRightString = dict.object(forKey: "bottomRightString") as! String
  159. model.dateFormatString = dict.object(forKey: "dateFormatString") as! String
  160. model.pageFormatString = dict.object(forKey: "pageFormatString") as! String
  161. model.startString = dict.object(forKey: "startString") as! String
  162. model.name = dict.object(forKey: "name") as! String
  163. if let value = dict.object(forKey: "tag") {
  164. model.tag = value as! String
  165. }
  166. NotificationCenter.default.post(name: KMHeaderFooterDatasUpdateNotiName, object: nil)
  167. }
  168. func updateCPDFHeaderFooter(_ headerFooter: CPDFHeaderFooter, withModel model: KMHeaderFooterModel, _ totalPDFCount: Int) {
  169. let fontSize = model.fontsize
  170. let fontName: String = model.fontName
  171. let font = NSFont.boldSystemFont(ofSize:fontSize)
  172. let style = NSMutableParagraphStyle()
  173. style.alignment = .center
  174. style.lineBreakMode = .byCharWrapping
  175. let size: NSSize = "text".boundingRect(with: NSSize(width: 1000, height: 1000), options: NSString.DrawingOptions(rawValue: 3), attributes: [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style]).size
  176. headerFooter.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin))
  177. let strings = KMHeaderFooterModel.parseModel(model: model, pageCount: totalPDFCount)
  178. var count: Int = 0
  179. let color = model.color
  180. for text in strings {
  181. headerFooter.setText(text, at: UInt(count))
  182. headerFooter.setTextColor(color, at: UInt(count))
  183. headerFooter.setFontSize(fontSize, at: UInt(count))
  184. headerFooter.setFontName(fontName, at: UInt(count))
  185. count += 1
  186. }
  187. }
  188. //MARK: - Parse
  189. func parseModel(model: KMHeaderFooterModel) -> Dictionary<String, Any> {
  190. var dict: [String : Any] = [:]
  191. dict["fontName"] = model.fontName
  192. dict["fontsize"] = model.fontsize
  193. dict["color"] = model.color.toHex()
  194. dict["leftMargin"] = model.leftMargin
  195. dict["rightMargin"] = model.rightMargin
  196. dict["bottomMargin"] = model.bottomMargin
  197. dict["topMargin"] = model.topMargin
  198. dict["topLeftString"] = model.topLeftString
  199. dict["topCenterString"] = model.topCenterString
  200. dict["topRightString"] = model.topRightString
  201. dict["bottomLeftString"] = model.bottomLeftString
  202. dict["bottomCenterString"] = model.bottomCenterString
  203. dict["bottomRightString"] = model.bottomRightString
  204. dict["dateFormatString"] = model.dateFormatString
  205. dict["pageFormatString"] = model.pageFormatString
  206. dict["startString"] = model.startString
  207. dict["name"] = model.name
  208. dict["tag"] = model.tag
  209. return dict
  210. }
  211. private func parseDictionary(dict: NSDictionary) -> KMHeaderFooterModel {
  212. let model = KMHeaderFooterModel()
  213. model.fontName = dict.object(forKey: "fontName") as! String
  214. model.fontsize = dict.object(forKey: "fontsize") as! CGFloat
  215. if let value = dict.object(forKey: "color") {
  216. model.color = NSColor.km_init(hex: value as! String)
  217. }
  218. model.leftMargin = dict.object(forKey: "leftMargin") as! Int
  219. model.rightMargin = dict.object(forKey: "rightMargin") as! Int
  220. model.bottomMargin = dict.object(forKey: "bottomMargin") as! Int
  221. model.topMargin = dict.object(forKey: "topMargin") as! Int
  222. model.topLeftString = dict.object(forKey: "topLeftString") as! String
  223. model.topCenterString = dict.object(forKey: "topCenterString") as! String
  224. model.topRightString = dict.object(forKey: "topRightString") as! String
  225. model.bottomLeftString = dict.object(forKey: "bottomLeftString") as! String
  226. model.bottomCenterString = dict.object(forKey: "bottomCenterString") as! String
  227. model.bottomRightString = dict.object(forKey: "bottomRightString") as! String
  228. model.dateFormatString = dict.object(forKey: "dateFormatString") as! String
  229. model.pageFormatString = dict.object(forKey: "pageFormatString") as! String
  230. model.startString = dict.object(forKey: "startString") as! String
  231. model.name = dict.object(forKey: "name") as! String
  232. model.tag = dict.object(forKey: "tag") as! String
  233. return model
  234. }
  235. //MARK: - Get
  236. func fetchHeaderFooterAvailableName() -> String {
  237. var availableIndex = 1
  238. for item in headFooterObjects {
  239. if item.name.hasPrefix("HeaderFooter-") {
  240. if let index = Int(item.name.dropFirst("HeaderFooter-".count)), index >= availableIndex {
  241. availableIndex = index + 1
  242. }
  243. }
  244. }
  245. return "HeaderFooter-\(availableIndex)"
  246. }
  247. //MARK: - Compare
  248. class func compareIsChangedModel(_ model: KMHeaderFooterModel, withDict dict: NSDictionary) -> Bool {
  249. if let value = dict["fontName"] {
  250. if model.fontName != (value as! String) {
  251. return true
  252. }
  253. }
  254. if let value = dict["fontsize"] {
  255. if model.fontsize != (value as! CGFloat) {
  256. return true
  257. }
  258. }
  259. if let value = dict["color"] {
  260. if model.color.toHex() != (value as! String) {
  261. return true
  262. }
  263. }
  264. if let value = dict["leftMargin"] {
  265. if model.leftMargin != (value as! Int) {
  266. return true
  267. }
  268. }
  269. if let value = dict["rightMargin"] {
  270. if model.rightMargin != (value as! Int) {
  271. return true
  272. }
  273. }
  274. if let value = dict["bottomMargin"] {
  275. if model.bottomMargin != (value as! Int) {
  276. return true
  277. }
  278. }
  279. if let value = dict["topMargin"] {
  280. if model.topMargin != (value as! Int) {
  281. return true
  282. }
  283. }
  284. if let value = dict["topLeftString"] {
  285. if model.topLeftString != (value as! String) {
  286. return true
  287. }
  288. }
  289. if let value = dict["topCenterString"] {
  290. if model.topCenterString != (value as! String) {
  291. return true
  292. }
  293. }
  294. if let value = dict["topRightString"] {
  295. if model.topRightString != (value as! String) {
  296. return true
  297. }
  298. }
  299. if let value = dict["bottomLeftString"] {
  300. if model.bottomLeftString != (value as! String) {
  301. return true
  302. }
  303. }
  304. if let value = dict["bottomCenterString"] {
  305. if model.bottomCenterString != (value as! String) {
  306. return true
  307. }
  308. }
  309. if let value = dict["bottomRightString"] {
  310. if model.bottomRightString != (value as! String) {
  311. return true
  312. }
  313. }
  314. if let value = dict["dateFormatString"] {
  315. if model.dateFormatString != (value as! String) {
  316. return true
  317. }
  318. }
  319. if let value = dict["pageFormatString"] {
  320. if model.pageFormatString != (value as! String) {
  321. return true
  322. }
  323. }
  324. if let value = dict["startString"] {
  325. if model.startString != (value as! String) {
  326. return true
  327. }
  328. }
  329. return false
  330. }
  331. }
  332. //MARK: - Class Method
  333. extension KMHeaderFooterManager {
  334. class func getdateFormatArray() -> [String] {
  335. return [
  336. "m/d",
  337. "m/d/yy",
  338. "m/d/yyyy",
  339. "mm/dd/yy",
  340. "mm/dd/yyyy",
  341. "d/m/yy",
  342. "d/m/yyyy",
  343. "dd/mm/yy",
  344. "dd/mm/yyyy",
  345. "mm/yy",
  346. "mm/yyyy",
  347. "m.d.yy",
  348. "m.d.yyyy",
  349. "mm.dd.yy",
  350. "mm.dd.yyyy",
  351. "mm.yy",
  352. "mm.yyyy",
  353. "d.m.yy",
  354. "d.m.yyyy",
  355. "dd.mm.yy",
  356. "dd.mm.yyyy",
  357. "yy-mm-dd",
  358. "yyyy-mm-dd"
  359. ]
  360. }
  361. class func getPageFormats() -> [String] {
  362. return ["1",
  363. "1 of n",
  364. "1/n",
  365. "Page 1",
  366. "Page 1 of n"]
  367. }
  368. class func getFontSize() -> [String] {
  369. return ["6","8","10","12","14",
  370. "16","18","20","22","24",
  371. "26","28","30","32","34",
  372. "36","40","48","64","80",
  373. "96","112"]
  374. }
  375. }