|
@@ -63,8 +63,8 @@ class KMMergeWindowController: NSWindowController {
|
|
|
|
|
|
}
|
|
|
|
|
|
- mergeView.mergeAction = { [unowned self] view in
|
|
|
-
|
|
|
+ mergeView.mergeAction = { [unowned self] view, files, size in
|
|
|
+ self.mergeFiles(files: files, size: size)
|
|
|
}
|
|
|
|
|
|
mergeView.cancelAction = { [unowned self] view in
|
|
@@ -136,4 +136,203 @@ extension KMMergeWindowController {
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ func mergeFiles(files: [KMFileAttribute], size: CGSize = CGSizeZero) {
|
|
|
+ if files.count <= 1 {
|
|
|
+ let alert = NSAlert.init()
|
|
|
+ alert.alertStyle = .critical
|
|
|
+ alert.messageText = NSLocalizedString("To start merging, please select at least 2 files.", comment: "")
|
|
|
+ alert.runModal()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+// _isSuccessfully = NO;
|
|
|
+// [self.nCancelVC setEnabled:NO];
|
|
|
+// self.canMerge = NO;
|
|
|
+//
|
|
|
+ var rootPDFOutlineArray: [PDFOutline] = []
|
|
|
+ var allPage = true //只有是全部才支持大纲的合并
|
|
|
+ for file in files {
|
|
|
+ if file.fetchSelectPages().count == 0 {
|
|
|
+ let alert = NSAlert.init()
|
|
|
+ alert.alertStyle = .critical
|
|
|
+ alert.messageText = "\(file.filePath.lastPathComponent) + \(NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: ""))"
|
|
|
+ alert.runModal()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ allPage = file.bAllPage
|
|
|
+
|
|
|
+ let tDocument = PDFDocument(url: NSURL(fileURLWithPath: file.filePath) as URL)!
|
|
|
+
|
|
|
+ var outlineArray: [PDFOutline] = []
|
|
|
+
|
|
|
+ if file.isLocked {
|
|
|
+ tDocument.unlock(withPassword: file.password!)
|
|
|
+ }
|
|
|
+
|
|
|
+ if tDocument.outlineRoot != nil {
|
|
|
+ rootPDFOutlineArray.append((tDocument.outlineRoot)!)
|
|
|
+ self.fetchAllOfChildren((tDocument.outlineRoot)!, containerArray: &outlineArray)
|
|
|
+ outlineArray.removeObject((tDocument.outlineRoot)!)
|
|
|
+ } else {
|
|
|
+ let rootOutline = PDFOutline.init()
|
|
|
+ tDocument.outlineRoot = rootOutline
|
|
|
+ if tDocument.outlineRoot != nil {
|
|
|
+ rootPDFOutlineArray.append(tDocument.outlineRoot!)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for number in file.fetchSelectPages() {
|
|
|
+ let page = tDocument.page(at: number.intValue - 1)
|
|
|
+ self.pdfDocument.insert(page!, at: self.pdfDocument.pageCount)
|
|
|
+// self.insertIndexSet.addIndex:(self.pdfDocument.pageCount - 1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ let fileName = (files.first?.filePath.lastPathComponent)! + "_Merged"
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self.pdfDocument.outlineRoot = PDFOutline.init()
|
|
|
+ if allPage {
|
|
|
+ var insertIndex = 0
|
|
|
+ for i in 0..<rootPDFOutlineArray.count {
|
|
|
+ let rootOutline = rootPDFOutlineArray[i]
|
|
|
+ for j in 0..<rootOutline.numberOfChildren {
|
|
|
+ self.pdfDocument.outlineRoot?.insertChild(rootOutline.child(at: j)!, at: insertIndex)
|
|
|
+ }
|
|
|
+ insertIndex = insertIndex + 1
|
|
|
+ }
|
|
|
+
|
|
|
+ self.handleReDraw()
|
|
|
+
|
|
|
+ let savePanelAccessoryViewController = KMSavePanelAccessoryController.init()
|
|
|
+ let savePanel = NSSavePanel()
|
|
|
+ savePanel.nameFieldStringValue = fileName
|
|
|
+ savePanel.allowedFileTypes = ["pdf"]
|
|
|
+ savePanel.accessoryView = savePanelAccessoryViewController.view
|
|
|
+// self.savePanelAccessoryViewController = savePanelAccessoryViewController;
|
|
|
+ savePanel.beginSheetModal(for: self.window!) { result in
|
|
|
+ if result != nil {
|
|
|
+ var outputSavePanel = savePanel.url?.path
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ var success = self.pdfDocument.write(toFile: outputSavePanel!)
|
|
|
+ if !success {
|
|
|
+ success = ((try?self.pdfDocument.dataRepresentation()?.write(to: URL(string: outputSavePanel!)!)) != nil)
|
|
|
+ }
|
|
|
+
|
|
|
+ if success {
|
|
|
+ if savePanelAccessoryViewController.needOpen {
|
|
|
+ NSDocumentController.shared.openDocument(withContentsOf: savePanel.url!, display: true) { document, open, error in
|
|
|
+
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ NSWorkspace.shared.activateFileViewerSelecting([NSURL(fileURLWithPath: outputSavePanel!) as URL])
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let alert = NSAlert.init()
|
|
|
+ alert.alertStyle = .critical
|
|
|
+ alert.messageText = "\(String(describing: files.first?.filePath.lastPathComponent)) + \(NSLocalizedString("Failed to merge!", comment: ""))"
|
|
|
+ alert.runModal()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func fetchAllOfChildren(_ aOutline: PDFOutline, containerArray aMArray: inout [PDFOutline]) {
|
|
|
+ if !aMArray.contains(aOutline) {
|
|
|
+ aMArray.append(aOutline)
|
|
|
+ }
|
|
|
+
|
|
|
+ for i in 0..<aOutline.numberOfChildren {
|
|
|
+ if let childOutline = aOutline.child(at: i) {
|
|
|
+ aMArray.append(childOutline)
|
|
|
+ fetchAllOfChildren(childOutline, containerArray: &aMArray)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func handleReDraw() {
|
|
|
+ if mergeView.originalSizeButton.state == .on {
|
|
|
+
|
|
|
+ } else {
|
|
|
+ let size = self.mergeView.newPageSize
|
|
|
+ if size.width < 0 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ var pagesArray: [PDFPage] = []
|
|
|
+ let pageCount = self.pdfDocument.pageCount
|
|
|
+ for i in 0..<pageCount {
|
|
|
+ pagesArray.append(self.pdfDocument.page(at: i)!)
|
|
|
+ self.pdfDocument.removePage(at: 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ for i in 0..<pageCount {
|
|
|
+ let page: KMMergePDFPage = KMMergePDFPage.init()
|
|
|
+ page.setBounds(CGRectMake(0, 0, size.width, size.height), for: .mediaBox)
|
|
|
+ page.drawingPage = pagesArray[i]
|
|
|
+ self.pdfDocument.insert(page, at: i)
|
|
|
+ }
|
|
|
+
|
|
|
+ if self.pdfDocument.outlineRoot != nil {
|
|
|
+ let childCount = self.pdfDocument.outlineRoot?.numberOfChildren
|
|
|
+ var outlineArray: [PDFOutline] = []
|
|
|
+
|
|
|
+ for i in 0..<childCount! {
|
|
|
+ outlineArray.append((self.pdfDocument.outlineRoot?.child(at: i))!)
|
|
|
+ }
|
|
|
+
|
|
|
+ for outline in outlineArray {
|
|
|
+ outline.removeFromParent()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class KMMergePDFPage: PDFPage {
|
|
|
+ var drawingPage: PDFPage?
|
|
|
+
|
|
|
+ override func draw(with box: PDFDisplayBox, to context: CGContext) {
|
|
|
+ super.draw(with: box, to: context)
|
|
|
+
|
|
|
+ let pageSize = self.bounds(for: .cropBox).size
|
|
|
+ self.drawPage(with: context, page: self.drawingPage!, pageSize: pageSize)
|
|
|
+ }
|
|
|
+
|
|
|
+ func drawPage(with context: CGContext, page: PDFPage, pageSize: CGSize) {
|
|
|
+ var originalSize = page.bounds(for: .cropBox).size
|
|
|
+
|
|
|
+ // 如果页面的旋转角度为90或者270,宽高交换
|
|
|
+ if page.rotation % 180 != 0 {
|
|
|
+ originalSize = CGSize(width: originalSize.height, height: originalSize.width)
|
|
|
+ }
|
|
|
+
|
|
|
+ let wRatio = pageSize.width / originalSize.width
|
|
|
+ let hRatio = pageSize.height / originalSize.height
|
|
|
+ let ratio = min(wRatio, hRatio)
|
|
|
+
|
|
|
+ context.saveGState()
|
|
|
+ let xTransform = (pageSize.width - originalSize.width * ratio) / 2
|
|
|
+ let yTransform = (pageSize.height - originalSize.height * ratio) / 2
|
|
|
+ context.translateBy(x: xTransform, y: yTransform)
|
|
|
+ context.scaleBy(x: ratio, y: ratio)
|
|
|
+
|
|
|
+ if #available(macOS 10.12, *) {
|
|
|
+ page.draw(with: .cropBox, to: context)
|
|
|
+ page.transformContext(for: .cropBox)
|
|
|
+ } else {
|
|
|
+ NSGraphicsContext.saveGraphicsState()
|
|
|
+ NSGraphicsContext.current = NSGraphicsContext(cgContext: context, flipped: false)
|
|
|
+ page.draw(with: .cropBox)
|
|
|
+ NSGraphicsContext.restoreGraphicsState()
|
|
|
+ page.transformContext(for: .cropBox)
|
|
|
+ }
|
|
|
+
|
|
|
+ context.restoreGState()
|
|
|
+ }
|
|
|
}
|