KMInfoWindowController.swift 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. //
  2. // KMInfoWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2023/10/10.
  6. //
  7. import Cocoa
  8. /*
  9. #define SKInfoWindowFrameAutosaveName @"SKInfoWindow"
  10. #define LABEL_COLUMN_ID @"label"
  11. #define VALUE_COLUMN_ID @"value"
  12. */
  13. private let LABEL_COLUMN_ID = "label"
  14. private let VALUE_COLUMN_ID = "value"
  15. private let KMInfoVersionKey = "Version"
  16. private let KMInfoPageCountKey = "PageCount"
  17. private let KMInfoPageSizeKey = "PageSize"
  18. private let KMInfoPageWidthKey = "PageWidth"
  19. private let KMInfoPageHeightKey = "PageHeight"
  20. private let KMInfoKeywordsStringKey = "Keywords"
  21. private let KMInfoEncryptedKey = "Encrypted"
  22. private let KMInfoAllowsPrintingKey = "AllowsPrinting"
  23. private let KMInfoAllowsCopyingKey = "AllowsCopying"
  24. private let KMInfoAllowsDocumentAssemblyKey = "AllowsDocumentAssembly"
  25. private let KMInfoAllowsContentAccessibilityKey = "AllowsContentAccessibility"
  26. private let KMInfoAllowsCommentingKey = "AllowsCommenting"
  27. private let KMInfoAllowsFormFieldEntryKey = "AllowsFormFieldEntry"
  28. private let KMInfoFileNameKey = "FileName"
  29. private let KMInfoFileSizeKey = "FileSize"
  30. private let KMInfoPhysicalSizeKey = "PhysicalSize"
  31. private let KMInfoLogicalSizeKey = "LogicalSize"
  32. private let KMInfoTagsKey = "Tags"
  33. private let KMInfoRatingKey = "Rating"
  34. private let kKMWindowDidBecomeMainNotificationName = Notification.Name(rawValue: "KMWindowDidBecomeMainNotificationName")
  35. typealias KMInfoWindowC = KMInfoWindowController
  36. class KMInfoWindowController: NSWindowController {
  37. public static let windowDidBecomeMainNotification = kKMWindowDidBecomeMainNotificationName
  38. @IBOutlet weak var summaryTableView: NSTableView!
  39. @IBOutlet weak var attributesTableView: NSTableView!
  40. @IBOutlet weak var tabView: NSTabView!
  41. var info: NSDictionary?
  42. var editDictionary: NSMutableDictionary = NSMutableDictionary()
  43. private var _summaryKeys: [String] = []
  44. var summaryKeys: [String] {
  45. get {
  46. return self._summaryKeys
  47. }
  48. }
  49. private var _attributesKeys: [String] = []
  50. var attributesKeys: [String] {
  51. get {
  52. return self._attributesKeys
  53. }
  54. }
  55. private var _labels: [String : String] = [:]
  56. var labels: [String : String] {
  57. get {
  58. return self._labels
  59. }
  60. }
  61. private weak var _currentDocument: NSDocument?
  62. deinit {
  63. NotificationCenter.default.removeObserver(self)
  64. Swift.debugPrint("KMInfoWindowController 已释放")
  65. }
  66. static let shared = KMInfoWindowController()
  67. convenience init() {
  68. self.init(windowNibName: "InfoWindow")
  69. self.info = nil;
  70. self._summaryKeys = [KMInfoFileNameKey,
  71. KMInfoFileSizeKey,
  72. KMInfoPageSizeKey,
  73. KMInfoPageCountKey,
  74. KMInfoVersionKey,
  75. "",
  76. KMInfoEncryptedKey,
  77. KMInfoAllowsPrintingKey,
  78. KMInfoAllowsCopyingKey,
  79. KMInfoAllowsDocumentAssemblyKey,
  80. KMInfoAllowsContentAccessibilityKey,
  81. KMInfoAllowsCommentingKey,
  82. KMInfoAllowsFormFieldEntryKey]
  83. self._attributesKeys = [PDFDocumentAttribute.titleAttribute.rawValue,
  84. PDFDocumentAttribute.authorAttribute.rawValue,
  85. PDFDocumentAttribute.subjectAttribute.rawValue,
  86. PDFDocumentAttribute.creatorAttribute.rawValue,
  87. PDFDocumentAttribute.producerAttribute.rawValue,
  88. PDFDocumentAttribute.creationDateAttribute.rawValue,
  89. PDFDocumentAttribute.modificationDateAttribute.rawValue,
  90. KMInfoKeywordsStringKey]
  91. self._labels = [KMInfoFileNameKey : KMLocalizedString("File name:"),
  92. KMInfoFileSizeKey : KMLocalizedString("File size:"),
  93. KMInfoPageSizeKey : KMLocalizedString("Page size:"),
  94. KMInfoPageCountKey : KMLocalizedString("Page count:"),
  95. KMInfoVersionKey : KMLocalizedString("PDF Version:"),
  96. KMInfoEncryptedKey : KMLocalizedString("Encrypted:"),
  97. KMInfoAllowsPrintingKey : KMLocalizedString("Printing:"),
  98. KMInfoAllowsCopyingKey : KMLocalizedString("Content Copying:"),
  99. KMInfoAllowsDocumentAssemblyKey : KMLocalizedString("Document Assembly:"),
  100. KMInfoAllowsContentAccessibilityKey : KMLocalizedString("Content Copying for Accessibility:"),
  101. KMInfoAllowsCommentingKey : KMLocalizedString("Commenting:"),
  102. KMInfoAllowsFormFieldEntryKey : KMLocalizedString("Filling of form fields:"),
  103. PDFDocumentAttribute.titleAttribute.rawValue : KMLocalizedString("Title:"),
  104. PDFDocumentAttribute.authorAttribute.rawValue : KMLocalizedString("Author:"),
  105. PDFDocumentAttribute.subjectAttribute.rawValue : KMLocalizedString("Subject:"),
  106. PDFDocumentAttribute.creatorAttribute.rawValue : KMLocalizedString("Content Creator:"),
  107. PDFDocumentAttribute.producerAttribute.rawValue : KMLocalizedString("PDF Producer:"),
  108. PDFDocumentAttribute.creationDateAttribute.rawValue : KMLocalizedString("Creation date:"),
  109. PDFDocumentAttribute.modificationDateAttribute.rawValue : KMLocalizedString("Modification date:"),
  110. KMInfoKeywordsStringKey : KMLocalizedString("Keywords:")]
  111. }
  112. override func loadWindow() {
  113. super.loadWindow()
  114. // self.window?.localizeStrings(fromTable: self.windowNibName)
  115. }
  116. override func windowDidLoad() {
  117. super.windowDidLoad()
  118. self.window?.title = NSLocalizedString("Document Info", comment: "")
  119. self.updateForDocument(NSApp.mainWindow?.windowController?.document as? NSDocument)
  120. self.summaryTableView.selectionHighlightStyle = .none
  121. self.attributesTableView.selectionHighlightStyle = .none
  122. for item in self.tabView.tabViewItems {
  123. if item.isEqual(to: self.tabView.tabViewItems.first) {
  124. item.label = NSLocalizedString("Summary", comment: "")
  125. } else {
  126. item.label = NSLocalizedString("Attributes", comment: "")
  127. }
  128. }
  129. self.tabView.selectTabViewItem(at: 1)
  130. NotificationCenter.default.addObserver(self, selector: #selector(_handleViewFrameDidChangeNotification), name: NSView.frameDidChangeNotification, object: self.attributesTableView.enclosingScrollView)
  131. NotificationCenter.default.addObserver(self, selector: #selector(_handleWindowDidBecomeMainNotification), name: NSWindow.didBecomeMainNotification, object: nil)
  132. NotificationCenter.default.addObserver(self, selector: #selector(_handleWindowDidResignMainNotification), name: NSWindow.didResignMainNotification, object: nil)
  133. NotificationCenter.default.addObserver(self, selector: #selector(_handlePDFDocumentInfoDidChangeNotification), name: NSNotification.Name.PDFDocumentDidUnlock, object: nil)
  134. NotificationCenter.default.addObserver(self, selector: #selector(_handleWindowWillCloseNotification), name: NSWindow.willCloseNotification, object: nil)
  135. NotificationCenter.default.addObserver(self, selector: #selector(_km_handleWindowDidBecomeMainNotification), name: KMInfoWindowC.windowDidBecomeMainNotification, object: nil)
  136. }
  137. func updateForDocument(_ doc: NSDocument?) {
  138. self._currentDocument = doc
  139. let info = self._infoForDocument(doc)
  140. var dic = NSMutableDictionary(dictionary: info)
  141. for key in self.editDictionary.allKeys {
  142. dic.setObject(self.editDictionary[key], forKey: key as! NSCopying)
  143. }
  144. self.info = dic
  145. self.summaryTableView.reloadData()
  146. self.attributesTableView.reloadData()
  147. }
  148. public func info(for document: NSDocument) -> NSDictionary {
  149. return self._infoForDocument(document)
  150. }
  151. // MARK: - Private Methods
  152. private func _infoForDocument(_ doc: NSDocument?) -> NSDictionary {
  153. var dictionary: NSMutableDictionary = NSMutableDictionary()
  154. var logicalSize: Int64 = 0
  155. var physicalSize: Int64 = 0
  156. if let data = doc, data.isKind(of: KMMainDocument.self) {
  157. if let pdfDoc = (data as! KMMainDocument).mainViewController?.document {
  158. dictionary.addEntries(from: pdfDoc.documentAttributes())
  159. dictionary.setValue(String(format: "%ld.%ld", pdfDoc.majorVersion, pdfDoc.minorVersion), forKey: KMInfoVersionKey)
  160. dictionary.setValue(NSNumber(value: pdfDoc.pageCount), forKey: KMInfoPageCountKey)
  161. if (pdfDoc.pageCount > 0) {
  162. let page: CPDFPage = pdfDoc.page(at:0)!
  163. let cropSize = page.bounds(for: .cropBox).size
  164. let mediaSize = page.bounds(for: .mediaBox).size
  165. dictionary.setValue(KMSizeString(cropSize, mediaSize), forKey: KMInfoPageSizeKey)
  166. dictionary.setValue(NSNumber(value: cropSize.width), forKey: KMInfoPageWidthKey)
  167. dictionary.setValue(NSNumber(value: cropSize.height), forKey: KMInfoPageHeightKey)
  168. }
  169. if let keyworks = dictionary.value(forKey: CPDFDocumentAttribute.keywordsAttribute.rawValue) {
  170. if (keyworks as AnyObject).isKind(of: NSArray.self) {
  171. dictionary.setValue(keyworks, forKey: KMInfoKeywordsStringKey)
  172. }
  173. }
  174. dictionary.setValue(NSNumber(booleanLiteral: pdfDoc.isEncrypted), forKey: KMInfoEncryptedKey)
  175. dictionary.setValue(NSNumber(booleanLiteral: pdfDoc.allowsPrinting), forKey: KMInfoAllowsPrintingKey)
  176. dictionary.setValue(NSNumber(booleanLiteral: pdfDoc.allowsCopying), forKey: KMInfoAllowsCopyingKey)
  177. dictionary.setValue(NSNumber(booleanLiteral: pdfDoc.allowsCommenting), forKey: KMInfoAllowsCommentingKey)
  178. dictionary.setValue(NSNumber(booleanLiteral: pdfDoc.allowsFormFieldEntry), forKey: KMInfoAllowsDocumentAssemblyKey)
  179. dictionary.setValue(NSNumber(booleanLiteral: pdfDoc.allowsFormFieldEntry), forKey: KMInfoAllowsFormFieldEntryKey)
  180. }
  181. }
  182. dictionary.setValue(doc?.fileURL?.path.lastPathComponent, forKey: KMInfoFileNameKey)
  183. dictionary.setValue(NSNumber(value: physicalSize), forKey: KMInfoPhysicalSizeKey)
  184. dictionary.setValue(NSNumber(value: logicalSize), forKey: KMInfoLogicalSizeKey)
  185. return dictionary
  186. }
  187. @objc private func _handleViewFrameDidChangeNotification(_ sender: Notification) {
  188. self.attributesTableView.noteHeightOfRows(withIndexesChanged: IndexSet(integer: self.attributesKeys.count-1))
  189. }
  190. @objc private func _handleWindowDidBecomeMainNotification(_ sender: Notification) {
  191. self.editDictionary.removeAllObjects()
  192. self.updateForDocument((sender.object as? NSWindow)?.windowController?.document as? NSDocument)
  193. }
  194. @objc private func _handleWindowDidResignMainNotification(_ sender: Notification) {
  195. self.editDictionary.removeAllObjects()
  196. self.updateForDocument(nil)
  197. }
  198. @objc private func _handlePDFDocumentInfoDidChangeNotification(_ sender: Notification) {
  199. guard let doc = NSApp.mainWindow?.windowController?.document else {
  200. return
  201. }
  202. if (doc.isKind(of: KMMainDocument.self)) {
  203. guard let pdfDocument = (doc as! KMMainDocument).mainViewController?.document else {
  204. return
  205. }
  206. if (pdfDocument.isEqual(to: sender.object)) {
  207. self.editDictionary.removeAllObjects()
  208. self.updateForDocument((doc as! NSDocument))
  209. }
  210. }
  211. }
  212. @objc private func _handleWindowWillCloseNotification(_ sender: Notification) {
  213. if let object = sender.object as? AnyObject, object.isEqual(self.window) {
  214. if (self.editDictionary.count > 0) {
  215. if let windowController = NSApp.mainWindow?.windowController, windowController.isKind(of: KMBrowserWindowController.self) {
  216. let document = (windowController as! KMBrowserWindowController).document as? KMMainDocument
  217. var dic: NSMutableDictionary = NSMutableDictionary(dictionary: document?.mainViewController?.document?.documentAttributes() ?? [:])
  218. var isSave = false
  219. for key in self.editDictionary.allKeys {
  220. if let data = key as? NSString, data.isEqual(to: KMInfoKeywordsStringKey) {
  221. let string = self.editDictionary[key]
  222. if let data = string as? NSString, data.isEqual(to: dic[PDFDocumentAttribute.keywordsAttribute.rawValue]) {
  223. isSave = true
  224. dic.setObject(string as Any, forKey: CPDFDocumentAttribute.keywordsAttribute.rawValue as NSCopying)
  225. }
  226. } else {
  227. if let data = dic[key] as? NSString, data.isEqual(to: self.editDictionary[key]) == false {
  228. isSave = true
  229. dic.setObject(self.editDictionary[key] as Any, forKey: key as! NSCopying)
  230. }
  231. }
  232. }
  233. if (isSave) {
  234. document?.mainViewController?.document?.setDocumentAttributes(dic as? [CPDFDocumentAttribute : Any])
  235. document?.save(nil)
  236. }
  237. }
  238. }
  239. self.editDictionary.removeAllObjects()
  240. }
  241. }
  242. @objc private func _km_handleWindowDidBecomeMainNotification(_ sender: Notification) {
  243. self.editDictionary.removeAllObjects()
  244. self.updateForDocument(sender.object as? NSDocument)
  245. }
  246. /*
  247. - (void)handlePDFDocumentInfoDidChangeNotification:(NSNotification *)notification {
  248. [self.editDictionary removeAllObjects];
  249. NSDocument *doc = [[[NSApp mainWindow] windowController] document];
  250. if ([doc isKindOfClass:[KMMainDocument class]]) {
  251. CPDFDocument *pdfDocument = ((KMMainDocument *)doc).mainViewController.document;
  252. if ([pdfDocument isEqual:notification.object]) {
  253. [self updateForDocument:doc];
  254. }
  255. }
  256. }
  257. - (void)handleDocumentFileURLDidChangeNotification:(NSNotification *)notification {
  258. [self.editDictionary removeAllObjects];
  259. NSDocument *doc = [[[NSApp mainWindow] windowController] document];
  260. if ([doc isEqual:[notification object]])
  261. [self updateForDocument:doc];
  262. }
  263. */
  264. override func showWindow(_ sender: Any?) {
  265. super.showWindow(sender)
  266. self.editDictionary.removeAllObjects()
  267. self.attributesTableView.reloadData()
  268. }
  269. /*
  270. #define BYTE_FACTOR 1024
  271. #define BYTE_FACTOR_F 1024.0f
  272. #define BYTE_SHIFT 10
  273. static NSString *SKFileSizeStringForFileURL(NSURL *fileURL, unsigned long long *physicalSizePtr, unsigned long long *logicalSizePtr) {
  274. if (fileURL == nil)
  275. return @"";
  276. FSRef fileRef;
  277. FSCatalogInfo catalogInfo;
  278. unsigned long long size, logicalSize = 0;
  279. BOOL gotSize = NO, isDir = NO;
  280. NSMutableString *string = [NSMutableString string];
  281. Boolean gotRef = CFURLGetFSRef((CFURLRef)fileURL, &fileRef);
  282. if (gotRef && noErr == FSGetCatalogInfo(&fileRef, kFSCatInfoDataSizes | kFSCatInfoRsrcSizes | kFSCatInfoNodeFlags, &catalogInfo, NULL, NULL, NULL)) {
  283. size = catalogInfo.dataPhysicalSize + catalogInfo.rsrcPhysicalSize;
  284. logicalSize = catalogInfo.dataLogicalSize + catalogInfo.rsrcLogicalSize;
  285. isDir = (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0;
  286. gotSize = YES;
  287. }
  288. if (gotSize == NO) {
  289. // this seems to give the logical size
  290. NSDictionary *fileAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:NULL];
  291. logicalSize = size = [[fileAttrs objectForKey:NSFileSize] unsignedLongLongValue];
  292. isDir = [[fileAttrs fileType] isEqualToString:NSFileTypeDirectory];
  293. }
  294. if (isDir) {
  295. NSString *path = [fileURL path];
  296. unsigned long long componentSize;
  297. unsigned long long logicalComponentSize;
  298. for (NSString *file in [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:path error:NULL]) {
  299. SKFileSizeStringForFileURL([NSURL fileURLWithPath:[path stringByAppendingPathComponent:file]], &componentSize, &logicalComponentSize);
  300. size += componentSize;
  301. logicalSize += logicalComponentSize;
  302. }
  303. }
  304. if (physicalSizePtr)
  305. *physicalSizePtr = size;
  306. if (logicalSizePtr)
  307. *logicalSizePtr = logicalSize;
  308. if (size < BYTE_FACTOR) {
  309. [string appendFormat:@"%qu %@", size, NSLocalizedString(@"bytes", @"size unit")];
  310. } else {
  311. #define numUnits 6
  312. NSString *units[numUnits] = {NSLocalizedString(@"kB", @"size unit"), NSLocalizedString(@"MB", @"size unit"), NSLocalizedString(@"GB", @"size unit"), NSLocalizedString(@"TB", @"size unit"), NSLocalizedString(@"PB", @"size unit"), NSLocalizedString(@"EB", @"size unit")};
  313. NSUInteger i;
  314. for (i = 0; i < numUnits; i++, size >>= BYTE_SHIFT) {
  315. if ((size >> BYTE_SHIFT) < BYTE_FACTOR || i == numUnits - 1) {
  316. [string appendFormat:@"%.1f %@", size / BYTE_FACTOR_F, units[i]];
  317. break;
  318. }
  319. }
  320. }
  321. NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
  322. [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
  323. [formatter setNumberStyle:NSNumberFormatterDecimalStyle];
  324. [string appendFormat:@" (%@ %@)", [formatter stringFromNumber:[NSNumber numberWithUnsignedLongLong:logicalSize]], NSLocalizedString(@"bytes", @"size unit")];
  325. return string;
  326. }
  327. - (NSArray *)keys {
  328. return [attributesKeys arrayByAddingObjectsFromArray:summaryKeys];
  329. }
  330. */
  331. }
  332. extension KMInfoWindowController: NSTableViewDelegate, NSTableViewDataSource {
  333. func numberOfRows(in tableView: NSTableView) -> Int {
  334. if (tableView.isEqual(to: self.summaryTableView)) {
  335. return self.summaryKeys.count
  336. } else if (tableView.isEqual(to: self.attributesTableView)) {
  337. return self.attributesKeys.count
  338. }
  339. return 0
  340. }
  341. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  342. var shortDateFormatter = DateFormatter()
  343. shortDateFormatter.dateStyle = .short
  344. shortDateFormatter.timeStyle = .none
  345. var keys: [String]?
  346. if (tableView.isEqual(to: self.summaryTableView)) {
  347. keys = self.summaryKeys
  348. } else if (tableView.isEqual(to: self.attributesTableView)) {
  349. keys = self.attributesKeys
  350. }
  351. let key = keys![row]
  352. let tcID = tableColumn?.identifier.rawValue
  353. var value: Any?
  354. if (key.isEmpty) {
  355. value = ""
  356. } else {
  357. if let data = tcID, data == LABEL_COLUMN_ID {
  358. value = self.labels[key] != nil ? self.labels[key] : key.appending(":")
  359. } else if let data = tcID, data == VALUE_COLUMN_ID {
  360. value = self.info?.object(forKey: key)
  361. if (value == nil) {
  362. value = "-"
  363. } else if let data = value as? NSDate {
  364. value = shortDateFormatter.string(from: data as Date)
  365. } else if let data = value as? NSNumber {
  366. if (key == KMInfoEncryptedKey) {
  367. value = data.boolValue ? KMLocalizedString("Yes") : KMLocalizedString("No")
  368. } else {
  369. value = key == KMInfoPageCountKey ? data.stringValue : (data.boolValue ? KMLocalizedString("Allowed") : KMLocalizedString("Not Allowed"))
  370. }
  371. }
  372. }
  373. }
  374. let cellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: tcID ?? ""), owner: self) as? NSTableCellView
  375. cellView?.textField?.stringValue = (value as? String) ?? ""
  376. if (tableView.isEqual(to: self.attributesTableView) && tableColumn?.identifier.rawValue == VALUE_COLUMN_ID) {
  377. if (row == 0 || row == 1 || row == 2 || row == 3 || row == 7) {
  378. cellView?.textField?.bezelStyle = .squareBezel
  379. cellView?.textField?.isEditable = true
  380. cellView?.textField?.isSelectable = true
  381. cellView?.textField?.isBordered = true
  382. cellView?.textField?.isBezeled = true
  383. cellView?.textField?.drawsBackground = true
  384. cellView?.textField?.delegate = self
  385. if (row == 1) {
  386. let cell = tableView.view(atColumn: 1, row: 0, makeIfNecessary: true) as? NSTableCellView
  387. cell?.textField?.nextKeyView = cellView!.textField
  388. } else if (row == 2) {
  389. let cell = tableView.view(atColumn: 1, row: 1, makeIfNecessary: true) as? NSTableCellView
  390. cell?.textField?.nextKeyView = cellView!.textField
  391. } else if (row == 3) {
  392. let cell = tableView.view(atColumn: 1, row: 2, makeIfNecessary: true) as? NSTableCellView
  393. cell?.textField?.nextKeyView = cellView!.textField
  394. } else if (row == 7) {
  395. let cell = tableView.view(atColumn: 1, row: 3, makeIfNecessary: true) as? NSTableCellView
  396. cell?.textField?.nextKeyView = cellView!.textField
  397. }
  398. } else {
  399. cellView?.textField?.isEditable = false
  400. cellView?.textField?.isSelectable = false
  401. cellView?.textField?.isBordered = false
  402. cellView?.textField?.isBezeled = false
  403. cellView?.textField?.drawsBackground = false
  404. cellView?.textField?.delegate = nil;
  405. }
  406. cellView?.textField?.tag = row
  407. }
  408. return cellView
  409. }
  410. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  411. var rowHeight = tableView.rowHeight
  412. if (tableView.isEqual(to: self.attributesTableView) && row == tableView.numberOfRows-1) {
  413. rowHeight = fmax(rowHeight, NSHeight(tableView.enclosingScrollView?.bounds ?? NSZeroRect) - tableView.numberOfRows.cgFloat * (rowHeight + tableView.intercellSpacing.height) + rowHeight)
  414. }
  415. return rowHeight
  416. }
  417. /*
  418. - (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
  419. static NSDateFormatter *shortDateFormatter = nil;
  420. if(shortDateFormatter == nil) {
  421. shortDateFormatter = [[NSDateFormatter alloc] init];
  422. [shortDateFormatter setDateStyle:NSDateFormatterShortStyle];
  423. [shortDateFormatter setTimeStyle:NSDateFormatterNoStyle];
  424. }
  425. NSArray *keys = nil;
  426. if ([tv isEqual:summaryTableView])
  427. keys = summaryKeys;
  428. else if ([tv isEqual:attributesTableView])
  429. keys = attributesKeys;
  430. NSString *key = [keys objectAtIndex:row];
  431. NSString *tcID = [tableColumn identifier];
  432. id value = nil;
  433. if ([key length]) {
  434. if ([tcID isEqualToString:LABEL_COLUMN_ID]) {
  435. value = [labels objectForKey:key] ?: [key stringByAppendingString:@":"];
  436. } else if ([tcID isEqualToString:VALUE_COLUMN_ID]) {
  437. value = [info objectForKey:key];
  438. if (value == nil)
  439. value = @"-";
  440. else if ([value isKindOfClass:[NSDate class]])
  441. value = [shortDateFormatter stringFromDate:value];
  442. else if ([value isKindOfClass:[NSNumber class]]){
  443. if ([key isEqualToString:SKInfoEncryptedKey]) {
  444. value = [value boolValue] ? NSLocalizedString(@"Yes", @"") : NSLocalizedString(@"No", @"");
  445. } else {
  446. value = ([key isEqualToString:SKInfoPageCountKey] ? [value stringValue] : ([value boolValue] ? NSLocalizedString(@"Allowed", @"") : NSLocalizedString(@"Not Allowed", @"")));
  447. }
  448. }
  449. }
  450. }
  451. return value;
  452. }
  453. - (void)tableView:(NSTableView *)tv willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
  454. if ([tv isEqual:attributesTableView] && [[tableColumn identifier] isEqualToString:LABEL_COLUMN_ID])
  455. [cell setLineBreakMode:row == [tv numberOfRows] - 1 ? NSLineBreakByWordWrapping : NSLineBreakByTruncatingTail];
  456. }
  457. - (CGFloat)tableView:(NSTableView *)tv heightOfRow:(NSInteger)row {
  458. CGFloat rowHeight = [tv rowHeight];
  459. if ([tv isEqual:attributesTableView] && row == [tv numberOfRows] - 1)
  460. rowHeight = fmax(rowHeight, NSHeight([[tv enclosingScrollView] bounds]) - [tv numberOfRows] * (rowHeight + [tv intercellSpacing].height) + rowHeight);
  461. return rowHeight;
  462. }
  463. - (BOOL)tableView:(NSTableView *)tv shouldSelectRow:(NSInteger)row {
  464. return YES;
  465. }
  466. - (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(nullable NSTabViewItem *)tabViewItem
  467. {
  468. if ([tabView indexOfTabViewItem:tabViewItem] == 1) {
  469. if (self.currentDocument) {
  470. NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:[self infoForDocument:self.currentDocument]];
  471. for (NSString *key in self.editDictionary.allKeys) {
  472. [dic setObject:self.editDictionary[key] forKey:key];
  473. }
  474. [self setInfo:dic];
  475. }
  476. [self.attributesTableView reloadData];
  477. } else {
  478. [self.summaryTableView reloadData];
  479. }
  480. }
  481. */
  482. }
  483. extension KMInfoWindowController: NSTextFieldDelegate {
  484. func controlTextDidChange(_ obj: Notification) {
  485. if let textField = obj.object as? NSTextField {
  486. if (textField.tag == 0) {
  487. self.editDictionary.setObject(textField.stringValue, forKey: PDFDocumentAttribute.titleAttribute.rawValue as NSCopying)
  488. } else if (textField.tag == 1) {
  489. self.editDictionary.setObject(textField.stringValue, forKey: PDFDocumentAttribute.authorAttribute.rawValue as NSCopying)
  490. } else if (textField.tag == 2) {
  491. self.editDictionary.setObject(textField.stringValue, forKey: PDFDocumentAttribute.subjectAttribute.rawValue as NSCopying)
  492. } else if (textField.tag == 3) {
  493. self.editDictionary.setObject(textField.stringValue, forKey: PDFDocumentAttribute.creatorAttribute.rawValue as NSCopying)
  494. } else if (textField.tag == 7) {
  495. self.editDictionary.setObject(textField.stringValue, forKey: KMInfoKeywordsStringKey as NSCopying)
  496. }
  497. }
  498. }
  499. }
  500. private let CM_PER_POINT = 0.035277778
  501. private let INCH_PER_POINT = 0.013888889
  502. private func KMSizeString(_ size: NSSize, _ altSize: NSSize) -> String {
  503. var useMetric = false
  504. if let data = ((NSLocale.current as NSLocale).object(forKey: .usesMetricSystem) as? NSNumber) {
  505. useMetric = data.boolValue
  506. }
  507. let factor = useMetric ? CM_PER_POINT : INCH_PER_POINT
  508. let units = useMetric ? KMLocalizedString("cm") : KMLocalizedString("in")
  509. if (NSEqualSizes(size, altSize)) {
  510. return String(format: "%.2f x %.2f %@", size.width * factor, size.height * factor, units)
  511. } else {
  512. return String(format: "%.2f x %.2f %@ (%.2f x %.2f %@)", size.width * factor, size.height * factor, units, altSize.width * factor, altSize.height * factor, units)
  513. }
  514. }