// // KMBrowser.swift // PDF Reader Pro // // Created by wanjun on 2022/12/9. // import Cocoa @objcMembers class KMBrowser: CTBrowser { var numberOfTabViewItem: Int = 0 var isCloseAllTabViewItem: Bool = false var currentCloseDocument: KMMainDocument? var currentDocument: KMMainDocument? deinit { KMPrint("KMBrowser deinit.") } override func createBlankTabBased(on baseContents: CTTabContents?) -> CTTabContents { return KMMainDocument.init(baseTabContents: baseContents)! } func createNewBrowser() -> KMBrowser { let browser = KMBrowser.init() as KMBrowser let cls = windowController != nil ? type(of: windowController) : CTBrowserWindowController.self browser.windowController = cls.init(browser: browser) return browser } override func windowDidBeginToClose() { self.currentDocument = NSDocumentController.shared.currentDocument as? KMMainDocument numberOfTabViewItem = Int(tabCount()) isCloseAllTabViewItem = true closeTabViewItem() } func closeTabViewItem() -> Void { if numberOfTabViewItem < 1 { window.orderOut(nil) tabStripModel.closeAllTabs() isCloseAllTabViewItem = false } else { let currentDocument = tabStripModel.tabContents(at: Int32(numberOfTabViewItem-1)) as! KMMainDocument if (currentDocument.isHome == false) { currentDocument.mainViewController?.savePageNumberIfNeed() if let _isEdited = currentDocument.mainViewController?.listView.isEdited(), _isEdited, !currentDocument.isDocumentEdited { currentDocument.updateChangeCount(.changeDone) } } // 清理数据 [主要清空通知] currentDocument.mainViewController?.clearData() self._trackCloseDocumentEvent() if (currentDocument.isEqual(to: self.currentDocument)) { // 当前文档 不用提醒,在关闭窗口时已提醒过了 tabStripModel.detachTabContents(at: Int32(self.numberOfTabViewItem - 1)) currentDocument.close() if (self.isCloseAllTabViewItem) { self.numberOfTabViewItem = self.numberOfTabViewItem - 1 self.closeTabViewItem() } return } let isPrompt = KMPreferenceManager.shared.closeFileIsPrompt() if currentDocument.isNewCreated { let exist = FileManager.default.fileExists(atPath: currentDocument.fileURL!.path) if exist { try? FileManager.default.removeItem(atPath: currentDocument.fileURL!.path) } currentCloseDocument = currentDocument currentDocument.runModalSavePanel(for: .saveAsOperation, delegate: self, didSave: #selector(saveSuccess(_:)), contextInfo: nil) } else { if currentDocument.isDocumentEdited && isPrompt { currentDocument.watermarkSaveDelegate = self currentDocument.canClose(withDelegate: self, shouldClose: #selector(document(_:shouldClose:contextInfo:)), contextInfo: nil) } else if currentDocument.isDocumentEdited { currentDocument.save(nil) currentDocument.close() if self.isCloseAllTabViewItem { numberOfTabViewItem = numberOfTabViewItem - 1 closeTabViewItem() } } else if (currentDocument.mainViewController != nil) { if (currentDocument.mainViewController!.isPDFDocumentEdited || currentDocument.mainViewController!.needSave) { if (isPrompt) { let alert = NSAlert() let message = "Do you want to save the changes made to the document “\(currentDocument.fileURL!.lastPathComponent)”?" alert.messageText = message alert.informativeText = NSLocalizedString("Your changes will be lost if you don’t save them.", comment: "") alert.addButton(withTitle: NSLocalizedString("Save", comment: "")) alert.addButton(withTitle: NSLocalizedString("Don‘t Save", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let response = alert.runModal() if (response == .alertFirstButtonReturn) { // 保存 currentDocument.save(nil) tabStripModel.detachTabContents(at: Int32(numberOfTabViewItem - 1)) currentDocument.close() } else if (response == .alertSecondButtonReturn) { // 不保存 tabStripModel.detachTabContents(at: Int32(numberOfTabViewItem - 1)) currentDocument.close() } else { // 取消 self.isCloseAllTabViewItem = false } } else { currentDocument.save(nil) currentDocument.close() } if isCloseAllTabViewItem { numberOfTabViewItem = numberOfTabViewItem - 1 closeTabViewItem() } } else { tabStripModel.detachTabContents(at: Int32(numberOfTabViewItem - 1)) currentDocument.close() if isCloseAllTabViewItem { numberOfTabViewItem = numberOfTabViewItem - 1 closeTabViewItem() } } } else { tabStripModel.detachTabContents(at: Int32(numberOfTabViewItem - 1)) currentDocument.close() if isCloseAllTabViewItem { numberOfTabViewItem = numberOfTabViewItem - 1 closeTabViewItem() } } } } } override func canCloseContents(at index: Int32) -> Bool { let isPrompt = KMPreferenceManager.shared.closeFileIsPrompt() if tabContents(at: Int32(index)) != nil { let currentDocument = tabContents(at: Int32(index)) as! KMMainDocument if (currentDocument.isHome == false) { currentDocument.mainViewController?.savePageNumberIfNeed() if let _isEdited = currentDocument.mainViewController?.listView.isEdited(), _isEdited, !currentDocument.isDocumentEdited { currentDocument.updateChangeCount(.changeDone) } } var canClose = false if currentDocument.isNewCreated { let exist = FileManager.default.fileExists(atPath: currentDocument.fileURL!.path) if exist { try? FileManager.default.removeItem(atPath: currentDocument.fileURL!.path) } currentCloseDocument = currentDocument currentDocument.runModalSavePanel(for: .saveToOperation, delegate: self, didSave: #selector(saveSuccess(_:)), contextInfo: nil) } else if (currentDocument.cloud) { /// 云文档 if (currentDocument.isDocumentEdited) { currentCloseDocument = currentDocument currentDocument.save(withDelegate: self, didSave: #selector(saveSuccess(_:)), contextInfo: nil) } else { currentDocument.close() canClose = true } } else { if currentDocument.isDocumentEdited && isPrompt { if currentDocument.isKind(of: KMMainDocument.self) { currentDocument.closedByUserGestureFlag = true } currentDocument.watermarkSaveDelegate = self currentDocument.canClose(withDelegate: self, shouldClose: #selector(document(_:shouldClose:contextInfo:)), contextInfo: nil) } else if currentDocument.isDocumentEdited { if (!currentDocument.needSaveWatermark()) { currentDocument.save(nil) currentDocument.close() canClose = true } else { currentDocument.watermarkSaveDelegate = self currentDocument.saveForWatermark() canClose = false } } else if (currentDocument.mainViewController != nil) { if (currentDocument.mainViewController!.isPDFDocumentEdited || currentDocument.mainViewController!.needSave) { if (isPrompt) { let alert = NSAlert() let message = "Do you want to save the changes made to the document “\(currentDocument.fileURL!.lastPathComponent)”?" alert.messageText = message alert.informativeText = NSLocalizedString("Your changes will be lost if you don’t save them.", comment: "") alert.addButton(withTitle: NSLocalizedString("Save", comment: "")) alert.addButton(withTitle: NSLocalizedString("Don‘t Save", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let response = alert.runModal() if (response == .alertFirstButtonReturn) { // 保存 if let home = self.tabContents(at: 0) as? KMMainDocument, home.isHome { // 标记 home 最近列表需要强制刷新 } currentDocument.save(nil) currentDocument.close() canClose = true } else if (response == .alertSecondButtonReturn) { // 不保存 currentDocument.close() canClose = true } else { // 取消 canClose = false } } else { currentDocument.save(nil) currentDocument.close() canClose = true } } else { currentDocument.close() canClose = true } } else { currentDocument.close() canClose = true } } if (canClose) { // 清理数据 [主要清空通知] currentDocument.mainViewController?.clearData() self._trackCloseDocumentEvent() } return canClose } return false } func document(_ document: NSDocument?, shouldClose: Bool, contextInfo: UnsafeMutableRawPointer?) { if (document is KMMainDocument) { let iu: CloseTypes = CLOSE_USER_GESTURE if ((document as! KMMainDocument).closedByUserGestureFlag && shouldClose) { (document as! KMMainDocument).closedByUserGesture = uint(iu.rawValue) } (document as! KMMainDocument).closedByUserGestureFlag = false } if (shouldClose) { let currentDocument: KMMainDocument = document! as! KMMainDocument let index = self.tabStripModel.index(of: currentDocument) // 清空数据 [主要清理通知] currentDocument.mainViewController?.clearData() self._trackCloseDocumentEvent() if index != kNoTab { self.tabStripModel.detachTabContents(at: index) } currentDocument.close() } } func saveSuccess(_ sender: Any) -> Void { if (currentCloseDocument != nil) { if (currentCloseDocument!.cloud) { /// 云文档 currentCloseDocument!.uploadToCloud({ [weak self] finished, error in if (finished) { if (self!.currentCloseDocument == nil) { return } let index = self?.tabStripModel.index(of: self!.currentCloseDocument!) self?.tabStripModel.detachTabContents(at: index!) self!.currentCloseDocument = nil if (self!.isCloseAllTabViewItem) { self!.numberOfTabViewItem = self!.numberOfTabViewItem - 1 self!.closeTabViewItem() } } }) return } if let isNewCreated = currentCloseDocument?.isNewCreated, isNewCreated { if let _url = currentCloseDocument?.saveToURL { // 将新创建的空白文档将入最近列表 NSDocumentController.shared.noteNewRecentDocumentURL(_url) } } let index = tabStripModel.index(of: currentCloseDocument) tabStripModel.detachTabContents(at: index) // 清空数据 [主要清理通知] currentCloseDocument?.mainViewController?.clearData() currentCloseDocument?.close() currentCloseDocument = nil self._trackCloseDocumentEvent() } if isCloseAllTabViewItem { numberOfTabViewItem = numberOfTabViewItem - 1 closeTabViewItem() } } func addNewTabContents() { if (self.tabCount() <= 0) { KMPrint("New Tab can‘t add first.") return } let contents = self.createBlankTabBased(on: nil) contents.isHome = true contents.isNewTab = true self.add(contents, at: -1, inForeground: true) } // MARK: - Private Methods private func _trackCloseDocumentEvent() { FMTrackEventManager.defaultManager.trackEvent(event: "Crash", withProperties: ["Crash_Trig" : "Crash_Trig_CloseDocument"]) } } extension KMBrowser { @objc public func canSelectNextTab() -> Bool { if (self.tabStripModel.count() < 1) { return false } if (self.tabStripModel.activeIndex >= (self.tabStripModel.count()-1)) { return false } return true } @objc public func canSelectPreviousTab() -> Bool { if (self.tabStripModel.activeIndex <= 0) { return false } return true } }