Browse Source

【2025】【页面编辑】补充页面编辑相关操作逻辑

dinglingui 4 months ago
parent
commit
1a95b9180e
23 changed files with 1358 additions and 269 deletions
  1. 7 32
      PDF Office/PDF Master/Class/Home/Category/CPDFDocument+PageEditManager.swift
  2. 6 2
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFExtract/KMNExtractPDFWindowController.swift
  3. 4 4
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFExtract/KMNExtractPDFWindowController.xib
  4. 1 1
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertBlankWindowController.swift
  5. 1 1
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertBlankWindowController.xib
  6. 6 6
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertClipboardWindowController.xib
  7. 0 2
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertPDFWindowController.swift
  8. 8 8
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertPDFWindowController.xib
  9. 201 6
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFSplit/KMNSplitPDFWindowController.swift
  10. 17 11
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFSplit/KMNSplitPDFWindowController.xib
  11. 70 15
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailManager.swift
  12. 317 25
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNPageEditViewController.swift
  13. 438 0
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailBaseViewController+Action.swift
  14. 118 121
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailBaseViewController.swift
  15. 1 1
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailBaseViewController.xib
  16. 49 0
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailCollectionView.swift
  17. 17 15
      PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailCollectionViewItem.swift
  18. 13 0
      PDF Office/PDF Master/KMClass/KMPDFViewController/KMPDFViewController.swift
  19. 2 2
      PDF Office/PDF Master/KMClass/KMPDFViewController/Toolbar/KMPDFSecToolbarController.xib
  20. 9 9
      PDF Office/PDF Master/KMClass/KMPDFViewController/Toolbar/Model/KMPDFToolbarManager.swift
  21. 49 0
      PDF Office/PDF Master/KMClass/Tools/Tool/KMNTools.swift
  22. BIN
      PDF Office/PDF Master/Source/default.metallib
  23. 24 8
      PDF Office/PDF Reader Pro.xcodeproj/project.pbxproj

+ 7 - 32
PDF Office/PDF Master/Class/Home/Category/CPDFDocument+PageEditManager.swift

@@ -70,14 +70,12 @@ extension CPDFDocument {
     func insertWithInsertPages(_ pages: [CPDFPage], insertPageIndex pageIndex: Int) -> Bool {
         var i = 0
         for (idx, page) in pages.enumerated() {
-//            if let copyP = page.copy() as? CPDFPage {
-                let reulst = self.insertPageObject(page, at: UInt(pageIndex + i))
-                i += 1
-//            }
+            let reulst = self.insertPageObject(page, at: UInt(pageIndex + i))
+            i += 1
         }
         return true
     }
-
+    
     func extractAsOneDocument(withPages pages: [CPDFPage], savePath: String?) -> Bool {
         let insertPages: [CPDFPage] = pages
         for i in 0...insertPages.count-1 {
@@ -86,11 +84,7 @@ extension CPDFDocument {
             self.insertPageObject(page, at: self.pageCount)
         }
         
-//        var writeSuccess = self.write(to: URL(fileURLWithPath: savePath!))
         var writeSuccess = self.write(toFile: savePath)
-//        if !writeSuccess {
-//            writeSuccess = NSData(data: self.dataRepresentation()).write(to: URL(fileURLWithPath: savePath!), atomically: true)
-//        }
         return writeSuccess
     }
     
@@ -102,7 +96,7 @@ extension CPDFDocument {
             pdf?.insertPageObject(page, at: pdf!.pageCount)
             var outPath = folerPath ?? ""
             let documentFileName = String(self.documentURL.lastPathComponent.split(separator: ".")[0]) ?? NSLocalizedString("Untitled", comment: "")
-
+            
             let dex = self.index(for: page) + 1
             outPath = URL(fileURLWithPath: outPath).appendingPathComponent(documentFileName).path
             outPath = String(format: "%@ page %ld", outPath, dex)
@@ -129,13 +123,11 @@ extension CPDFDocument {
             if (j == 1) {
                 fileCount += 1
                 tdocument = CPDFDocument()
-//                let page = self.page(at: i).copy()
                 let page = self.page(at: i)
                 tdocument?.insertPageObject((page!), at: tdocument!.pageCount)
                 if (j == splitPageCount) {
                     let filePath = "\(folerPath)/\(fileName) \(fileCount).pdf"
                     isSuccessfull = tdocument?.write(toFile: filePath) ?? false
-//                    tdocument = nil
                     j = 1
                     if (!isSuccessfull) {
                         break
@@ -147,19 +139,16 @@ extension CPDFDocument {
                 }
             } else if (j == splitPageCount) {
                 j = 1
-//                let page = self.page(at: i).copy()
                 let page = self.page(at: i)
                 tdocument?.insertPageObject((page!), at: tdocument!.pageCount)
                 let filePath = "\(folerPath)/\(fileName) \(fileCount).pdf"
                 isSuccessfull = tdocument?.write(toFile: filePath) ?? false
-//                tdocument = nil
                 if (!isSuccessfull) {
                     break
                 } else {
                     successArray.append(filePath)
                 }
             } else {
-//                let page = self.page(at: i).copy()
                 let page = self.page(at: i)
                 tdocument?.insertPageObject((page!), at: tdocument!.pageCount)
                 j += 1
@@ -169,7 +158,6 @@ extension CPDFDocument {
                 if (tdocument != nil) {
                     let filePath = "\(folerPath)/\(fileName) \(fileCount).pdf"
                     isSuccessfull = tdocument?.write(toFile: filePath) ?? false
-//                    tdocument = nil
                     if (!isSuccessfull) {
                         break
                     } else {
@@ -201,14 +189,11 @@ extension CPDFDocument {
                     averagelyCount = Int(pageCount)-averagelyCount*(fileCount-1)
                 }
                 tdocument = CPDFDocument()
-//                PDFPage * page = [[[self pageAtIndex:i]copy] autorelease];
                 let page = self.page(at: i)
-//                [tdocument insertPage:page atIndex:[tdocument pageCount]];
                 tdocument?.insertPageObject(page!, at: tdocument?.pageCount ?? 0)
                 if (j == averagelyCount) {
-//                    NSString *tPath = [folerPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %ld.pdf",fileName,fileCount]];
                     let tPath = "\(folerPath)/\(fileName) \(fileCount).pdf"
-
+                    
                     isSuccessfull = tdocument!.write(toFile: tPath)
                     tdocument = nil
                     j = 1
@@ -222,13 +207,10 @@ extension CPDFDocument {
                 }
             } else if (j == averagelyCount) {
                 j = 1
-//                PDFPage * page = [[[self pageAtIndex:i]copy] autorelease];
                 let page = self.page(at: i)
-//                [tdocument insertPage:page atIndex:[tdocument pageCount]];
                 tdocument?.insertPageObject(page!, at: tdocument?.pageCount ?? 0)
-//                NSString *tPath = [folerPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %ld.pdf",fileName,fileCount]];
                 let tPath = "\(folerPath)/\(fileName) \(fileCount).pdf"
-
+                
                 isSuccessfull = tdocument!.write(toFile: tPath)
                 tdocument = nil
                 if (!isSuccessfull) {
@@ -237,16 +219,13 @@ extension CPDFDocument {
                     successArray.append(tPath)
                 }
             } else{
-//                PDFPage * page = [[[self pageAtIndex:i]copy] autorelease];
                 let page = self.page(at: i)
                 
-//                [tdocument insertPage:page atIndex:[tdocument pageCount]];
                 tdocument?.insertPageObject(page!, at: tdocument?.pageCount ?? 0)
                 j += 1
             }
             if (i == pageCount-1) {
                 if (tdocument != nil) {
-//                    NSString *tPath = [folerPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ %ld.pdf",fileName,fileCount]];
                     let tPath = "\(folerPath)/\(fileName) \(fileCount).pdf"
                     
                     isSuccessfull = tdocument!.write(toFile: tPath)
@@ -269,7 +248,7 @@ extension CPDFDocument {
     func splitByFileWithPages(_ fileAttribute: KMFileAttribute, folerPath: String, fileName: String) -> [String]? {
         var isSuccessfull = false
         var successArray: [String] = []
-
+        
         var pdfDocument1 = CPDFDocument()
         var pdfDocument2 = CPDFDocument()
         for i in 0 ..< self.pageCount {
@@ -277,21 +256,18 @@ extension CPDFDocument {
             for number in fileAttribute.fetchSelectPages() {
                 if number == i+1 {
                     isSelected = true
-//                    PDFPage *page = [[self pageAtIndex:i] copy];
                     if let page = self.page(at: i) {
                         pdfDocument1?.insertPageObject(page, at: pdfDocument1?.pageCount ?? 0)
                     }
                 }
             }
             if (!isSelected) {
-//                PDFPage *page = [[self pageAtIndex:i] copy];
                 if let page = self.page(at: i) {
                     pdfDocument2?.insertPageObject(page, at: pdfDocument2?.pageCount ?? 0)
                 }
             }
         }
         if let cnt = pdfDocument1?.pageCount, cnt > 0 {
-//            NSString *tPath = [folerPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ 1.pdf",fileName]];
             let tPath = "\(folerPath)/\(fileName) 1.pdf"
             isSuccessfull = pdfDocument1?.write(toFile: tPath) ?? false
             if (isSuccessfull) {
@@ -301,7 +277,6 @@ extension CPDFDocument {
             }
         }
         if let cnt = pdfDocument2?.pageCount, cnt > 0 {
-//            NSString *tPath = [folerPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ 2.pdf",fileName]];
             let tPath = "\(folerPath)/\(fileName) 2.pdf"
             isSuccessfull = pdfDocument2?.write(toFile: tPath) ?? false
             if (isSuccessfull) {

+ 6 - 2
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFExtract/KMNExtractPDFWindowController.swift

@@ -24,6 +24,8 @@ class KMNExtractPDFWindowController: KMNBaseWindowController {
     private var orgDocument:CPDFDocument?
     private var selectionIndexPaths: Set<IndexPath> = []
     
+    var callback: ((Bool, Bool)->Void)?
+    
     private func setUpProperty() {
         titleLabel.stringValue = KMLocalizedString("Extract")
         titleLabel.font =  ComponentLibrary.shared.getFontFromKey("mac/body-m-medium")
@@ -101,8 +103,8 @@ class KMNExtractPDFWindowController: KMNBaseWindowController {
     }
     
     @objc func extractButtonClicked(_ sender: NSView) {
-                
-        own_closeEndSheet()
+        
+        callback?(eachButton.properties.checkboxType == .selected,deleteButton.properties.checkboxType == .selected)
     }
 
     @objc func eachPDFAction(_ sender: NSView) {
@@ -111,5 +113,7 @@ class KMNExtractPDFWindowController: KMNBaseWindowController {
     @objc func deletePDFAction(_ sender: NSView) {
                 
     }
+    
+    
 }
 

+ 4 - 4
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFExtract/KMNExtractPDFWindowController.xib

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -24,7 +24,7 @@
             <windowStyleMask key="styleMask" titled="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <rect key="contentRect" x="196" y="240" width="480" height="270"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
             <view key="contentView" id="se5-gp-TjO">
                 <rect key="frame" x="0.0" y="0.0" width="480" height="208"/>
                 <autoresizingMask key="autoresizingMask"/>
@@ -35,7 +35,7 @@
                             <rect key="frame" x="0.0" y="0.0" width="432" height="168"/>
                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                             <subviews>
-                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FVy-lR-qve">
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="FVy-lR-qve">
                                     <rect key="frame" x="-2" y="152" width="436" height="16"/>
                                     <textFieldCell key="cell" lineBreakMode="clipping" title="Extract" id="f9j-2x-IVQ">
                                         <font key="font" usesAppearanceFont="YES"/>

+ 1 - 1
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertBlankWindowController.swift

@@ -415,7 +415,7 @@ class KMNPDFInsertBlankWindowController: KMNBaseWindowController {
             standardSelect.properties.isDisabled = false
             standardSelect.reloadData()
         } else if sender == customizationRadioButton {
-            if(firstRadioButton.properties.checkboxType == .selected) {
+            if(currentRadioButton.properties.checkboxType == .selected) {
                 oldSelectRadioBtn = currentRadioButton
             } else if (standardRadioButton.properties.checkboxType == .selected){
                 oldSelectRadioBtn = standardRadioButton

+ 1 - 1
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertBlankWindowController.xib

@@ -44,7 +44,7 @@
             <windowStyleMask key="styleMask" titled="YES" fullSizeContentView="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <rect key="contentRect" x="196" y="240" width="495" height="553"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="1512" height="944"/>
             <view key="contentView" id="se5-gp-TjO">
                 <rect key="frame" x="0.0" y="0.0" width="480" height="504"/>
                 <autoresizingMask key="autoresizingMask"/>

+ 6 - 6
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertClipboardWindowController.xib

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -30,7 +30,7 @@
             <windowStyleMask key="styleMask" titled="YES" fullSizeContentView="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <rect key="contentRect" x="196" y="240" width="480" height="270"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="1512" height="944"/>
             <view key="contentView" id="se5-gp-TjO">
                 <rect key="frame" x="0.0" y="0.0" width="480" height="248"/>
                 <autoresizingMask key="autoresizingMask"/>
@@ -41,7 +41,7 @@
                             <rect key="frame" x="0.0" y="0.0" width="432" height="216"/>
                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                             <subviews>
-                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AiR-qt-ZiL">
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AiR-qt-ZiL">
                                     <rect key="frame" x="-2" y="200" width="436" height="16"/>
                                     <textFieldCell key="cell" lineBreakMode="clipping" title="Insert from Clipboard" id="XkL-Nc-SHI">
                                         <font key="font" usesAppearanceFont="YES"/>
@@ -97,7 +97,7 @@
                                                     <constraint firstAttribute="height" constant="20" id="jxD-uV-Tlb"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vvh-mZ-hZZ">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vvh-mZ-hZZ">
                                                 <rect key="frame" x="-2" y="108" width="436" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="Insertion Position" id="Pzv-T6-WIY">
                                                     <font key="font" usesAppearanceFont="YES"/>
@@ -125,7 +125,7 @@
                                                     <constraint firstAttribute="height" constant="32" id="TF4-EP-Uk3"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0y2-gu-PB5">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0y2-gu-PB5">
                                                 <rect key="frame" x="194" y="16" width="32" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="/200" id="MwL-z3-jqh">
                                                     <font key="font" usesAppearanceFont="YES"/>

+ 0 - 2
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertPDFWindowController.swift

@@ -419,8 +419,6 @@ extension KMNPDFInsertPDFWindowController: ComponentSelectDelegate {
             }
             pageRangeSelect.reloadData()
             
-        } else if (view == positionSelect) {
-            
         }
     }
 }

+ 8 - 8
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFInsert/KMNPDFInsertPDFWindowController.xib

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -35,7 +35,7 @@
             <windowStyleMask key="styleMask" titled="YES" fullSizeContentView="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <rect key="contentRect" x="196" y="240" width="557" height="563"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="1512" height="944"/>
             <view key="contentView" id="se5-gp-TjO">
                 <rect key="frame" x="0.0" y="0.0" width="480" height="372"/>
                 <autoresizingMask key="autoresizingMask"/>
@@ -46,7 +46,7 @@
                             <rect key="frame" x="0.0" y="0.0" width="432" height="340"/>
                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                             <subviews>
-                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nVt-ye-20v">
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nVt-ye-20v">
                                     <rect key="frame" x="-2" y="324" width="436" height="16"/>
                                     <textFieldCell key="cell" lineBreakMode="clipping" title="Insert File" id="S0u-WL-oBc">
                                         <font key="font" usesAppearanceFont="YES"/>
@@ -72,7 +72,7 @@
                                                     <constraint firstAttribute="height" constant="32" id="vqe-8f-ty4"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vLC-Uy-bWz">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vLC-Uy-bWz">
                                                 <rect key="frame" x="-2" y="84" width="436" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="Form File" id="ELj-Y5-Gb3">
                                                     <font key="font" usesAppearanceFont="YES"/>
@@ -80,7 +80,7 @@
                                                     <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                 </textFieldCell>
                                             </textField>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2mp-wK-3MJ">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="2mp-wK-3MJ">
                                                 <rect key="frame" x="-2" y="8" width="80" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="Page Range:" id="fiE-1K-NiO">
                                                     <font key="font" usesAppearanceFont="YES"/>
@@ -132,7 +132,7 @@
                                                     <constraint firstAttribute="height" constant="20" id="X4e-au-sQo"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="e7a-sg-bz8">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="e7a-sg-bz8">
                                                 <rect key="frame" x="-2" y="108" width="436" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="Form File" id="IcN-r8-Kef">
                                                     <font key="font" usesAppearanceFont="YES"/>
@@ -160,7 +160,7 @@
                                                     <constraint firstAttribute="height" constant="32" id="Bvo-ul-zuG"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dMn-2x-fc2">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dMn-2x-fc2">
                                                 <rect key="frame" x="194" y="16" width="32" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="/200" id="d0w-sT-Tgo">
                                                     <font key="font" usesAppearanceFont="YES"/>

+ 201 - 6
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFSplit/KMNSplitPDFWindowController.swift

@@ -10,6 +10,8 @@ import Cocoa
 import KMComponentLibrary
 
 class KMNSplitPDFWindowController: KMNBaseWindowController {
+    @IBOutlet var progress: NSProgressIndicator!
+
     @IBOutlet var titleLabel: NSTextField!
     
     @IBOutlet var methodLabel: NSTextField!
@@ -45,6 +47,12 @@ class KMNSplitPDFWindowController: KMNBaseWindowController {
 
     private var orgDocument:CPDFDocument?
     private var selectionIndexPaths: Set<IndexPath> = []
+    
+    private func viewFileAtFinder(_ filePath: String) {
+        let workspace = NSWorkspace.shared
+        let url = URL(fileURLWithPath: filePath)
+        workspace.activateFileViewerSelecting([url])
+    }
 
     private func setUpProperty() {
         titleLabel.stringValue = KMLocalizedString("Split")
@@ -66,7 +74,7 @@ class KMNSplitPDFWindowController: KMNBaseWindowController {
                                                                text: KMLocalizedString("Split by every"),
                                                                checkboxType: .normal)
         averagePernLabel.stringValue = KMLocalizedString("page(s)")
-        averagePernLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/1")
+        averagePernLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("comp-field/colorText-filled-dis")
         averagePernLabel.font =  ComponentLibrary.shared.getFontFromKey("comp-field/colorText-filled-dis")
 
         averageSplitRadio.properties = ComponentCheckBoxProperty(size: .s,
@@ -114,7 +122,7 @@ class KMNSplitPDFWindowController: KMNBaseWindowController {
                                                                           state: .normal,
                                                                           isError: false,
                                                                           showErrorInfo: false,
-                                                                          isDisabled: false,
+                                                                          isDisabled: true,
                                                                           showPrefix: false,
                                                                           showSuffix: false,
                                                                           minSize: 1,
@@ -145,7 +153,8 @@ class KMNSplitPDFWindowController: KMNBaseWindowController {
                                                                            placeholder: "",
                                                                            text: "Part")
         tagInput.properties = inputTagProperty
-        
+        tagInput.delegate = self
+
         let inputSeparatorProperty: ComponentInputProperty = ComponentInputProperty(size: .s,
                                                                            state:.pressed ,
                                                                            isError: false,
@@ -156,6 +165,7 @@ class KMNSplitPDFWindowController: KMNBaseWindowController {
                                                                            placeholder: "",
                                                                            text: "-")
         separatorInput.properties = inputSeparatorProperty
+        separatorInput.delegate = self
         
         splitRangeSelect.properties = ComponentSelectProperties(size: .s,
                                                                 state: .normal,
@@ -245,6 +255,7 @@ class KMNSplitPDFWindowController: KMNBaseWindowController {
         splitRangeSelect.reloadData()
         
         updateFileName()
+        progress.isHidden = true
     }
     
     func updateFileName() {
@@ -317,8 +328,182 @@ class KMNSplitPDFWindowController: KMNBaseWindowController {
     }
     
     @objc func splitButtonClicked(_ sender: NSView) {
+        let pageRangeSelectIndex = splitRangeSelect.indexOfSelect()
+        let fileAttribute = KMNFileAttribute()
+        if(splitRangeRadio.properties.checkboxType == .selected) {
+            fileAttribute.password = orgDocument?.password ?? ""
+            fileAttribute.filePath =  orgDocument?.documentURL.path ?? ""
+            if(pageRangeSelectIndex == 0) {
+                fileAttribute.bAllPage = false
+                fileAttribute.pagesType = .OnlyOdd
+            } else {
+                fileAttribute.bAllPage = false
+                if(orgDocument?.pageCount ?? 0 <= 1) {
+                    fileAttribute.pagesType = .PagesString
+                    fileAttribute.pagesString = splitRangeSelect.properties.text ?? ""
+                } else {
+                    if(pageRangeSelectIndex == 2) {
+                        fileAttribute.pagesType = .OnlyEven
+                    } else {
+                        fileAttribute.pagesType = .PagesString
+                        fileAttribute.pagesString = splitRangeSelect.properties.text ?? ""
+                    }
+                }
+            }
+            
+            if (fileAttribute.fetchSelectPages().isEmpty) {
+                let alert = NSAlert()
+                alert.alertStyle = .critical
+                alert.messageText = String(format: "%@ %@", fileAttribute.filePath.lastPathComponent, KMLocalizedString("Invalid page range or the page number is out of range. Please try again."))
+                alert.runModal()
+                return
+            }
+        }
+        
+        let panel = NSOpenPanel()
+        panel.canChooseFiles = false
+        panel.canChooseDirectories = true
+        panel.canCreateDirectories = true
+        panel.beginSheetModal(for: self.window!) { result in
+            if (result == .OK) {
+                let outputURL = panel.urls.first
+                var tFolderPath = outputURL!.path
                 
-        own_closeEndSheet()
+                var index = 0
+                let folderName = self.fileNameLabel.stringValue.deletingPathExtension.lastPathComponent
+                var folderPath = "\(tFolderPath)" + "/" + "\(folderName)"
+                //创建目录
+                while FileManager.default.fileExists(atPath: folderPath) {
+                    index += 1
+                    folderPath = "\(tFolderPath)" + "/" + "\(folderName)_\(index)"
+                }
+                tFolderPath = folderPath
+                try?FileManager.default.createDirectory(atPath: tFolderPath, withIntermediateDirectories: true)
+                
+                self.progress.isHidden = false
+                self.cancelButton.properties.isDisabled = true
+                self.splitButton.properties.isDisabled = true
+                self.cancelButton.reloadData()
+                self.splitButton.reloadData()
+                
+                self.progress.startAnimation(nil)
+                
+                if(self.averagePerRadio.properties.checkboxType == .selected) {
+                    let index = Int(self.averagePernInputNumber.properties.text ?? "1")
+                    DispatchQueue.global().async {
+                        let successArray = self.orgDocument?.splitByPagesWith(index ?? 1, folerPath: tFolderPath, fileName: folderName) ?? []
+                        DispatchQueue.main.async {
+                            self.progress.isHidden = true
+                            self.cancelButton.properties.isDisabled = false
+                            self.splitButton.properties.isDisabled = false
+                            
+                            self.cancelButton.reloadData()
+                            self.splitButton.reloadData()
+                            
+                            if (successArray.isEmpty == false) {
+                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder."), buttons: [KMLocalizedString("OK")])
+                                if (response == .alertFirstButtonReturn ) {
+                                    self.own_closeEndSheet()
+                                    DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
+                                        let filePath = successArray.first ?? ""
+                                        self.viewFileAtFinder(filePath)
+                                    }
+                                }
+                            } else {
+                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Failed to split!"))
+                                if (response == .alertFirstButtonReturn) {
+                                    self.own_closeEndSheet()
+                                }
+                            }
+                        }
+                    }
+                } else if(self.averageSplitRadio.properties.checkboxType == .selected) {
+                    let dex = Int(self.averageSplitInputNumber.properties.text ?? "1")
+                    DispatchQueue.global().async {
+                        let successArray = self.orgDocument?.splitByFileWith(dex ?? 1, folerPath: tFolderPath, fileName: folderName) ?? []
+                        DispatchQueue.main.async {
+                            self.progress.isHidden = true
+                            self.cancelButton.properties.isDisabled = false
+                            self.splitButton.properties.isDisabled = false
+                            self.cancelButton.reloadData()
+                            self.splitButton.reloadData()
+                            
+                            if (successArray.isEmpty == false) {
+                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder."), buttons: [KMLocalizedString("OK")])
+                                if (response == .alertFirstButtonReturn) {
+                                    self.own_closeEndSheet()
+                                    DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
+                                        let filePath = successArray.first ?? ""
+                                        self.viewFileAtFinder(filePath)
+                                    }
+                                }
+                            }else{
+                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Failed to split!"))
+                                if (response == .alertFirstButtonReturn) {
+                                    self.own_closeEndSheet()
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    var isSuccessfully:Bool = false
+                    
+                    DispatchQueue.global().async { [self] in
+                        var pdfDocument1 = CPDFDocument()
+                        var pdfDocument2 = CPDFDocument()
+                        let pageCnt = self.orgDocument?.pageCount ?? 0
+                        let pages = fileAttribute.fetchSelectPages()
+                        for i in 0 ..< pageCnt {
+                            var isSelected = false
+                            for number in pages {
+                                if number == i+1 {
+                                    isSelected = true
+                                    if let page = self.orgDocument?.page(at: i) as? CPDFPage {
+                                        pdfDocument1?.insertPageObject(page, at: pdfDocument1!.pageCount)
+                                    }
+                                }
+                            }
+                            if (!isSelected) {
+                                if let page = self.orgDocument?.page(at: i) as? CPDFPage {
+                                    pdfDocument2?.insertPageObject(page, at: pdfDocument2!.pageCount)
+                                }
+                            }
+                        }
+                        if (pdfDocument1!.pageCount > 0) {
+                            let tpath = "\(tFolderPath)/\(folderName) 1.pdf"
+                            isSuccessfully = pdfDocument1?.write(toFile:tpath) ?? false
+                        }
+                        if (pdfDocument2!.pageCount > 0) {
+                            let tPath = "\(tFolderPath)/\(folderName) 2.pdf"
+                            pdfDocument2?.write(toFile: tPath)
+                        }
+                        DispatchQueue.main.async {
+                            self.progress.isHidden = true
+                            self.cancelButton.properties.isDisabled = false
+                            self.splitButton.properties.isDisabled = false
+                            self.cancelButton.reloadData()
+                            self.splitButton.reloadData()
+                            
+                            if (isSuccessfully) {
+                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder."), buttons: [KMLocalizedString("OK")])
+                                if (response == .alertFirstButtonReturn) {
+                                    self.own_closeEndSheet()
+                                    DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
+                                        let filePath = "\(tFolderPath)/\(folderName) 1.pdf"
+                                        self.viewFileAtFinder(filePath)
+                                    }
+                                }
+                            } else {
+                                let response = KMAlertTool.runModelForMainThread_r(message: KMLocalizedString("Failed to split!"))
+                                if (response == .alertFirstButtonReturn) {
+                                    self.own_closeEndSheet()
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
     
     @objc func changeNameClick(_ sender: NSView){
@@ -411,8 +596,18 @@ extension KMNSplitPDFWindowController: ComponentSelectDelegate {
                 splitRangeSelect.properties.creatable = false
             }
             splitRangeSelect.reloadData()
-            
-            
         }
     }
 }
+
+extension KMNSplitPDFWindowController: ComponentInputDelegate {
+    func componentInputDidEndEditing(inputView: ComponentInput) {
+        
+    }
+    
+    func componentInputDidChanged(inputView: ComponentInput) {
+        updateFileName()
+    }
+    
+}
+

+ 17 - 11
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNPDFSplit/KMNSplitPDFWindowController.xib

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
@@ -23,6 +23,7 @@
                 <outlet property="fileTitleLabel" destination="E7d-kr-3NP" id="lbd-9A-IEr"/>
                 <outlet property="methodLabel" destination="UQm-9R-ufX" id="DNH-Wf-Xaj"/>
                 <outlet property="precedeCheckBox" destination="ns0-6a-3Zb" id="36m-bT-Pbt"/>
+                <outlet property="progress" destination="TiY-FI-9RS" id="WXS-Pu-eof"/>
                 <outlet property="separatorCheckBox" destination="cHx-41-a4x" id="grJ-CN-EyI"/>
                 <outlet property="separatorCheckWidthButton" destination="Abe-jb-3iL" id="ATb-a1-i7X"/>
                 <outlet property="separatorInput" destination="TZS-vp-GuO" id="mxR-rj-mIO"/>
@@ -44,7 +45,7 @@
             <windowStyleMask key="styleMask" titled="YES" fullSizeContentView="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <rect key="contentRect" x="196" y="240" width="480" height="270"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
             <view key="contentView" id="se5-gp-TjO">
                 <rect key="frame" x="0.0" y="0.0" width="480" height="502"/>
                 <autoresizingMask key="autoresizingMask"/>
@@ -55,7 +56,7 @@
                             <rect key="frame" x="0.0" y="0.0" width="432" height="470"/>
                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                             <subviews>
-                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="jDk-6k-wPg">
+                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="jDk-6k-wPg">
                                     <rect key="frame" x="-2" y="454" width="436" height="16"/>
                                     <textFieldCell key="cell" lineBreakMode="clipping" title="Split" id="cYm-fs-fJs">
                                         <font key="font" usesAppearanceFont="YES"/>
@@ -83,7 +84,7 @@
                                                     <constraint firstAttribute="height" constant="32" id="gdP-n3-RdE"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UQm-9R-ufX">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UQm-9R-ufX">
                                                 <rect key="frame" x="-2" y="138" width="436" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="Split Method" id="cI1-Kj-hfi">
                                                     <font key="font" usesAppearanceFont="YES"/>
@@ -111,7 +112,7 @@
                                                     <constraint firstAttribute="height" constant="32" id="wWO-v0-kf7"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="taE-wg-hAl">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="taE-wg-hAl">
                                                 <rect key="frame" x="208" y="102" width="226" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="page(s) split into a PDF file" id="Xjj-Vz-9HY">
                                                     <font key="font" metaFont="system"/>
@@ -126,7 +127,7 @@
                                                     <constraint firstAttribute="height" constant="32" id="xt9-QO-Oc7"/>
                                                 </constraints>
                                             </customView>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hSV-Fh-E6f">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hSV-Fh-E6f">
                                                 <rect key="frame" x="210" y="62" width="224" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="PDF files" id="uMu-7j-jve">
                                                     <font key="font" metaFont="system"/>
@@ -198,7 +199,7 @@
                                         <rect key="frame" x="0.0" y="0.0" width="432" height="64"/>
                                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                         <subviews>
-                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="E7d-kr-3NP">
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="E7d-kr-3NP">
                                                 <rect key="frame" x="-2" y="40" width="436" height="16"/>
                                                 <textFieldCell key="cell" lineBreakMode="clipping" title="File Name" id="zp9-BF-8N0">
                                                     <font key="font" usesAppearanceFont="YES"/>
@@ -212,7 +213,7 @@
                                                     <rect key="frame" x="0.0" y="0.0" width="432" height="32"/>
                                                     <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                     <subviews>
-                                                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="G4G-Lb-K8M">
+                                                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="G4G-Lb-K8M">
                                                             <rect key="frame" x="3" y="8" width="426" height="16"/>
                                                             <textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="Split Method" id="SGc-TN-nF0">
                                                                 <font key="font" usesAppearanceFont="YES"/>
@@ -264,7 +265,7 @@
                                                 </constraints>
                                             </customView>
                                             <customView translatesAutoresizingMaskIntoConstraints="NO" id="q8l-c0-d1C" customClass="ComponentInput" customModule="KMComponentLibrary">
-                                                <rect key="frame" x="108" y="48" width="324" height="32"/>
+                                                <rect key="frame" x="108" y="48" width="323" height="32"/>
                                                 <constraints>
                                                     <constraint firstAttribute="height" constant="32" id="j8M-RB-nhU"/>
                                                 </constraints>
@@ -287,7 +288,7 @@
                                             <constraint firstAttribute="bottom" secondItem="cHx-41-a4x" secondAttribute="bottom" constant="8" id="BIw-ce-7OJ"/>
                                             <constraint firstItem="TZS-vp-GuO" firstAttribute="leading" secondItem="cHx-41-a4x" secondAttribute="trailing" constant="8" id="CCS-sM-Baz"/>
                                             <constraint firstItem="cHx-41-a4x" firstAttribute="top" secondItem="fBw-l2-vHD" secondAttribute="bottom" constant="8" id="Cvf-zI-gsk"/>
-                                            <constraint firstAttribute="trailing" secondItem="q8l-c0-d1C" secondAttribute="trailing" id="Gl5-V5-pJx"/>
+                                            <constraint firstAttribute="trailing" secondItem="q8l-c0-d1C" secondAttribute="trailing" constant="1" id="Gl5-V5-pJx"/>
                                             <constraint firstItem="TZS-vp-GuO" firstAttribute="centerY" secondItem="cHx-41-a4x" secondAttribute="centerY" id="JDq-8E-FRg"/>
                                             <constraint firstItem="fBw-l2-vHD" firstAttribute="top" secondItem="ns0-6a-3Zb" secondAttribute="bottom" constant="8" id="JFf-aZ-Os5"/>
                                             <constraint firstItem="fBw-l2-vHD" firstAttribute="leading" secondItem="WVS-PN-b7f" secondAttribute="leading" id="Xcw-cr-VcB"/>
@@ -325,9 +326,14 @@
                             <constraint firstAttribute="width" constant="432" id="G1P-tA-ma2"/>
                         </constraints>
                     </box>
+                    <progressIndicator maxValue="100" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="TiY-FI-9RS">
+                        <rect key="frame" x="224" y="235" width="32" height="32"/>
+                    </progressIndicator>
                 </subviews>
                 <constraints>
                     <constraint firstAttribute="trailing" secondItem="J6U-4A-QXu" secondAttribute="trailing" constant="24" id="0tf-1Z-2Rg"/>
+                    <constraint firstItem="TiY-FI-9RS" firstAttribute="centerX" secondItem="se5-gp-TjO" secondAttribute="centerX" id="3O0-4w-MVf"/>
+                    <constraint firstItem="TiY-FI-9RS" firstAttribute="centerY" secondItem="se5-gp-TjO" secondAttribute="centerY" id="P91-KB-OHd"/>
                     <constraint firstItem="J6U-4A-QXu" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="16" id="n1z-oG-V7N"/>
                     <constraint firstItem="J6U-4A-QXu" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="24" id="uOi-8Q-nuw"/>
                     <constraint firstAttribute="bottom" secondItem="J6U-4A-QXu" secondAttribute="bottom" constant="16" id="xjT-Ol-pjb"/>

+ 70 - 15
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailManager.swift

@@ -34,12 +34,8 @@ public class KMNThumbnail: NSObject {
         pageIndex = currentPageIndex
         let page = document.page(at: UInt(currentPageIndex))
         let size =  page?.bounds.size ?? CGSizeZero
-        if (page?.rotation ?? 0) % 180 == 0 {
-            pageSize = size
-        } else {
-            pageSize = CGSize(width: size.height, height: size.width)
+        pageSize = size
 
-        }
         thumbnaiPage = page
         pageRotate = 0
         
@@ -60,14 +56,17 @@ public class KMNThumbnail: NSObject {
         if !fileManager.fileExists(atPath: docsFilePath) {
             try? FileManager.default.createDirectory(atPath: docsFilePath, withIntermediateDirectories: true, attributes: nil)
         }
-        let imageFilePath = docsFilePath + "/" + (self.thumbnaiPage?.label ?? String(self.pageIndex)) + ".png"
         
-        if fileManager.fileExists(atPath: imageFilePath) {
-           let image = NSImage.init(contentsOfFile: imageFilePath) ?? NSImage()
-            if completion != nil {
-                completion!(image)
-            }
+        let pageObjNum = thumbnaiPage?.getObjNum() ?? -1 //获取Page的唯一标识码
+        var imageFilePath = ""
+
+        if(pageObjNum == -1) {
+            imageFilePath = ""
         } else {
+            imageFilePath =  docsFilePath + "/" + String(pageObjNum) + ".png"
+        }
+        
+        if(imageFilePath.isEmpty == true) {
             var thumSize = pageSize
             if pageSize.width < 100 {
                 thumSize.width = 100
@@ -75,7 +74,9 @@ public class KMNThumbnail: NSObject {
             }
             
             thumbnaiPage?.thumbnail(of: thumSize, needReset: true,completion: { pageImage in
-
+                if completion != nil {
+                    completion!(pageImage)
+                }
                 // 将 NSImage 转换为 PNG 数据
                 guard let tiffData = pageImage?.tiffRepresentation,
                          let bitmapImage = NSBitmapImageRep(data: tiffData),
@@ -88,24 +89,78 @@ public class KMNThumbnail: NSObject {
                    } catch {
                    }
                 
+            });
+        } else {
+            if fileManager.fileExists(atPath: imageFilePath) {
+               let image = NSImage.init(contentsOfFile: imageFilePath) ?? NSImage()
                 if completion != nil {
-                    completion!(pageImage)
+                    completion!(image)
                 }
-            });
+            } else {
+                var thumSize = pageSize
+                if pageSize.width < 100 {
+                    thumSize.width = 100
+                    thumSize.height *= 100/pageSize.width
+                }
+                
+                thumbnaiPage?.thumbnail(of: thumSize, needReset: true,completion: { pageImage in
+                    if completion != nil {
+                        completion!(pageImage)
+                    }
+                    // 将 NSImage 转换为 PNG 数据
+                    guard let tiffData = pageImage?.tiffRepresentation,
+                             let bitmapImage = NSBitmapImageRep(data: tiffData),
+                             let pngData = bitmapImage.representation(using: .png, properties: [:]) else {
+                           return
+                       }
+
+                       do {
+                           try pngData.write(to: URL(fileURLWithPath: imageFilePath))
+                       } catch {
+                       }
+                    
+                });
+            }
         }
     }
     
     fileprivate func fileId(for document: CPDFDocument) -> String {
         return "\(document.documentURL.path.hash)"
     }
+    
+    func removeCacheImage() {
+        let filePathID = fileId(for: thumbnailDocument)
+        let docsFilePath = kmnThumbnailFolder + "/" + filePathID
+        let fileManager = FileManager.default
+
+        let pageObjNum = thumbnaiPage?.getObjNum() ?? -1
+        var imageFilePath = ""
+
+        if(pageObjNum == -1) {
+            imageFilePath = ""
+        } else {
+            imageFilePath =  docsFilePath + "/" + String(pageObjNum) + ".png"
+        }
+                
+        if fileManager.fileExists(atPath: imageFilePath) {
+           try? fileManager.removeItem(atPath: imageFilePath)
+        }
+    }
 }
 
 class KMNThumbnailManager: NSObject {
     
+    static let manager = KMNThumbnailManager()
+    
+    var copyPages: [CPDFPage] = []
+    
+    var copyDocument: [CPDFDocument] = []
+
     class func clearCacheThumImage() {
         if FileManager.default.fileExists(atPath: kmnThumbnailFolder) {
             try?FileManager.default.removeItem(atPath: kmnThumbnailFolder)
         }
-
     }
+    
+    
 }

+ 317 - 25
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNPageEditViewController.swift

@@ -20,9 +20,92 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
         super.viewDidLoad()
          
          self.backViewBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-pdfView")
+         
+         collectionView.menuClickedAction = { point in
+             return self.clickMenu(point: point)
+         }
     }
     
-    public func insertFromPDFAction() {
+    private func clickMenu(point:NSPoint)->NSMenu {
+        let copyPages: [CPDFPage] = KMNThumbnailManager.manager.copyPages
+
+        let menu = NSMenu()
+        // 根据 clickPoint 创建菜单项
+        let copyMenuItem = NSMenuItem(title: KMLocalizedString("Copy"), action: #selector(copyMenuItemAciton), target: self)
+        copyMenuItem.keyEquivalent = "c"
+                
+        let pastMenuItem = NSMenuItem(title: KMLocalizedString("Paste"), action: #selector(pastMenuItemAciton), target: self)
+        pastMenuItem.keyEquivalent = "v"
+        
+        let pastNullMenuItem = NSMenuItem(title: KMLocalizedString("Paste"), action: nil, target: self)
+        pastNullMenuItem.keyEquivalent = "v"
+        
+        let cutMenuItem = NSMenuItem(title: KMLocalizedString("Cut"), action: #selector(cutMenuItemAciton), target: self)
+        cutMenuItem.keyEquivalent = "x"
+        
+        let deleteMenuItem = NSMenuItem(title: KMLocalizedString("Delete"), action: #selector(deleteMenuItemAciton), target: self)
+        deleteMenuItem.keyEquivalent = String(Unicode.Scalar(NSBackspaceCharacter)!)
+
+        let rotateLeftMenuItem = NSMenuItem(title: KMLocalizedString("90° CCW"), action: #selector(rotatePageLeftAction), target: self)
+        rotateLeftMenuItem.keyEquivalent = "l" // 设置为字母 l
+        rotateLeftMenuItem.keyEquivalentModifierMask = [.option, .command] // 设置为 Option + Command
+
+        let rotateRightMenuItem = NSMenuItem(title: KMLocalizedString("90° CW"), action: #selector(rotatePageRightAction), target: self)
+        rotateRightMenuItem.keyEquivalent = "r" // 设置为字母 r
+        rotateRightMenuItem.keyEquivalentModifierMask = [.option, .command] // 设置为 Option + Command
+
+        let insertFileMenuItem = NSMenuItem(title: KMLocalizedString("Insert File"), action: #selector(insertFromPDFAction), target: self)
+
+        let insertBlankMenuItem = NSMenuItem(title: KMLocalizedString("Insert a Blank Page"), action: #selector(insertFromBlankAction), target: self)
+        
+        let replaceMenuItem = NSMenuItem(title: KMLocalizedString("Replace"), action: #selector(replacePDFAction), target: self)
+        
+        let extractMenuItem = NSMenuItem(title: KMLocalizedString("Export"), action: #selector(extractPDFAction), target: self)
+        
+        let shareMenuItem = NSMenuItem(title: KMLocalizedString("Share"), action: nil, target: self)
+        
+        shareMenuItem.submenu = NSSharingServicePicker.menu(forSharingItems: [showDocument?.documentURL ?? ""], subjectContext: "", withTarget: self, selector: NSSelectorFromString("sharePageItemAction:"), serviceDelegate: nil)
+        
+        let showFileSizeMenuItem = NSMenuItem(title: KMLocalizedString("Display Page Size"), action: #selector(displayPageSizeAction), target: self)
+        showFileSizeMenuItem.state = isShowPageSize ? .on : .off
+        
+        let selectedIndexPaths = collectionView.selectionIndexPaths
+
+        if(selectedIndexPaths.count > 0) {
+            menu.addItem(copyMenuItem)
+            menu.addItem(cutMenuItem)
+            if(copyPages.count > 0) {
+                menu.addItem(pastMenuItem)
+            }
+            menu.addItem(deleteMenuItem)
+            menu.addItem(NSMenuItem.separator())
+            menu.addItem(rotateRightMenuItem)
+            menu.addItem(rotateLeftMenuItem)
+            menu.addItem(NSMenuItem.separator())
+            if(selectedIndexPaths.count == 1) {
+                menu.addItem(insertFileMenuItem)
+                menu.addItem(insertBlankMenuItem)
+                menu.addItem(replaceMenuItem)
+            }
+            menu.addItem(extractMenuItem)
+            menu.addItem(shareMenuItem)
+            menu.addItem(NSMenuItem.separator())
+            menu.addItem(showFileSizeMenuItem)
+        } else {
+            if(copyPages.count > 0) {
+                menu.addItem(pastMenuItem)
+                menu.addItem(NSMenuItem.separator())
+            } else {
+                menu.addItem(pastNullMenuItem)
+                menu.addItem(NSMenuItem.separator())
+            }
+            menu.addItem(showFileSizeMenuItem)
+        }
+
+        return menu
+    }
+    
+    @objc public func insertFromPDFAction() {
         if IAPProductsManager.default().isAvailableAllFunction() == false {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
@@ -30,6 +113,7 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
 
         let selectedIndexPaths = collectionView.selectionIndexPaths
         let minimumIndexPath = selectedIndexPaths.min(by: { $0 < $1 })
+        let open = NSOpenPanel()
 
         let insertPDF = KMNPDFInsertPDFWindowController(self.showDocument, currentPageIndex: minimumIndexPath?.item ?? 0)
         insertPDF.callback = { [weak self] fileAttribute, insertIdx in
@@ -53,16 +137,16 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
         insertPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
     }
     
-    public func insertFromBlankAction() {
+    @objc public func insertFromBlankAction() {
         if IAPProductsManager.default().isAvailableAllFunction() == false {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
         }
         
         let selectedIndexPaths = collectionView.selectionIndexPaths
-        let minimumIndexPath = selectedIndexPaths.min(by: { $0 < $1 })
+        let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
 
-        let insertPDF = KMNPDFInsertBlankWindowController(self.showDocument, currentPageIndex: minimumIndexPath?.item ?? 0)
+        let insertPDF = KMNPDFInsertBlankWindowController(self.showDocument, currentPageIndex: maxmumIndexPath?.item ?? 0)
         insertPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
     }
     
@@ -72,9 +156,9 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
             return
         }
         let selectedIndexPaths = collectionView.selectionIndexPaths
-        let minimumIndexPath = selectedIndexPaths.min(by: { $0 < $1 })
+        let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
 
-        let insertPDF = KMNPDFInsertClipboardWindowController(self.showDocument, currentPageIndex: minimumIndexPath?.item ?? 0)
+        let insertPDF = KMNPDFInsertClipboardWindowController(self.showDocument, currentPageIndex: maxmumIndexPath?.item ?? 0)
         insertPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
     }
     
@@ -83,18 +167,36 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
         }
+        
         let selectedIndexPaths = collectionView.selectionIndexPaths
-        let minimumIndexPath = selectedIndexPaths.min(by: { $0 < $1 })
+        let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
 
-        let insertPDF = KMNPDFInsertClipboardWindowController(self.showDocument, currentPageIndex: minimumIndexPath?.item ?? 0)
-        insertPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
+        let vc = KMDeviceBrowserWindowController.shared
+        vc.type = .scanner
+        vc.importScannerFileCallback = { [weak self] (url: NSURL) -> Void in
+            if let imag = NSImage(contentsOfFile: url.path! ) {
+                let index = (maxmumIndexPath?.item ?? 0) + 1
+                let document = CPDFDocument()
+                _ = document?.km_insertPage(imag.size, withImage: url.path! , at:UInt(index))
+                self?.refreshDatas()
+               
+            }
+        }
+        vc.showWindow(nil)
+        vc.window?.center()
     }
     
     public func canZoomInPageSize()->Bool {
+        if pageThumbnailSize.width > defaultItemSize.width {
+            return false
+        }
         return true
     }
     
     public func canZoomOutPageSize()->Bool {
+        if pageThumbnailSize.width < defaultItemSize.width {
+            return false
+        }
         return true
     }
     
@@ -114,32 +216,67 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
         return true
     }
     
-    public func extractPDFAction() {
+    @objc public func extractPDFAction() {
         if IAPProductsManager.default().isAvailableAllFunction() == false {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
         }
 
-        if collectionView.selectionIndexPaths.count < 1 {
+        let selectedIndexPaths = collectionView.selectionIndexPaths
+
+        if selectedIndexPaths.count < 1 {
             _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
             return
         }
                 
         let extractPDF = KMNExtractPDFWindowController(self.showDocument, selectionIndexPaths: collectionView.selectionIndexPaths)
+        extractPDF.callback = { [weak self] oneDocumentPerPage, isDeletePage in
+            extractPDF.own_closeEndSheet()
+            if let _ = self?.showDocument {
+                self?.extractPages(indexpaths: selectedIndexPaths, oneDocumentPerPage: oneDocumentPerPage, callback: { [weak self] result, params in
+                    if (result == .failure || result == .cancel) {
+                        return
+                    }
+                    if (isDeletePage) {
+                        self?.deletePages(indexpaths: selectedIndexPaths)
+                    }
+                })
+            }
+        }
         extractPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
-        
     }
     
-    public func replacePDFAction() {
+    @objc public func replacePDFAction() {
         if IAPProductsManager.default().isAvailableAllFunction() == false {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
         }
-        if collectionView.selectionIndexPaths.count < 1 {
+        
+        let selectedIndexPaths = collectionView.selectionIndexPaths
+        
+        if selectedIndexPaths.count < 1 {
             _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
             return
         }
         
+        self.km_open_file_multi {  [unowned self] index, params in
+            if (self.fetchProgressBlockParamsIsPasswordFile(params: params)) { // 加密文档进度回调
+                return
+            }
+            
+            let tFileUrl = self.fetchProgressBlockParamsForFileUrl(params: params)
+            let pdfExtensions = KMNConvertTool.supportPDFFileType()
+            if let exn = tFileUrl?.pathExtension, pdfExtensions.contains(exn)  {
+                if (tFileUrl!.path.isPDFValid() == false) {
+                    let alert = NSAlert()
+                    alert.alertStyle = .critical
+                    alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
+                    alert.runModal()
+                }
+            }
+        } completionBlock: { [unowned self] documents in
+            self.replacePages(of: selectedIndexPaths, with: documents)
+        }
     }
     
     public func splitPDFAction() {
@@ -149,8 +286,7 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
         }
         
         let selectedIndexPaths = collectionView.selectionIndexPaths
-        let minimumIndexPath = selectedIndexPaths.min(by: { $0 < $1 })
-
+        
         if collectionView.selectionIndexPaths.count < 1 {
             _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.bounds.origin.x + self.view.bounds.size.width/2, self.view.bounds.size.height - 30))
             return
@@ -166,14 +302,16 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
         }
-        if collectionView.selectionIndexPaths.count < 1 {
-            _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
+        let selectedIndexPaths = collectionView.selectionIndexPaths
+        
+        if selectedIndexPaths.count < 2 {
+            _ = KMNCustomAlertView.alertView(message: KMLocalizedString("No page selected. Please select at least two pages to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
             return
         }
-
+        reversePages(indexs: self.indexpathsToIndexs(indexpaths: selectedIndexPaths))
     }
     
-    public func rotatePageLeftAction() {
+    @objc public func rotatePageLeftAction() {
         if IAPProductsManager.default().isAvailableAllFunction() == false {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
@@ -183,10 +321,10 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
             _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
             return
         }
-        
+        rotatePages(indexPaths: collectionView.selectionIndexPaths, rotateAngle: -90)
     }
     
-    public func rotatePageRightAction() {
+    @objc public func rotatePageRightAction() {
         if IAPProductsManager.default().isAvailableAllFunction() == false {
             KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
             return
@@ -196,7 +334,7 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
             _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
             return
         }
-        
+        rotatePages(indexPaths: collectionView.selectionIndexPaths, rotateAngle: 90)
     }
     
     public func deletePageAction() {
@@ -205,23 +343,177 @@ class KMNPageEditViewController: KMNThumbnailBaseViewController {
             return
         }
         
-        if collectionView.selectionIndexPaths.count < 1 {
+        let selectedIndexPaths = collectionView.selectionIndexPaths
+
+        if selectedIndexPaths.count < 1 {
             _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
             return
-        } else if collectionView.selectionIndexPaths.count == (showDocument?.pageCount ?? 0) {
+        } else if selectedIndexPaths.count == (showDocument?.pageCount ?? 0) {
             _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Can not delete all pages."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
             return
 
         }
         
+        deletePages(indexpaths: selectedIndexPaths)
     }
     
     public func zoomInPageAction() { //放大
+        if (canZoomInPageSize() == false) {
+            return
+        }
+        let indexpaths = collectionView.selectionIndexPaths
+
+        if (pageThumbnailSize.width < defaultItemSize.width) {
+            pageThumbnailSize = defaultItemSize
+        } else if (pageThumbnailSize.width == defaultItemSize.width) {
+            pageThumbnailSize = NSSize(width: defaultItemSize.width*1.5, height: defaultItemSize.height*1.5)
+        }
         
+        collectionView.reloadData()
+        collectionView.selectionIndexPaths = indexpaths
     }
     
     public func zoomOutPageAction() { //缩小
+        if (canZoomOutPageSize() == false) {
+            return
+        }
+        let indexpaths = collectionView.selectionIndexPaths
+
+        if (pageThumbnailSize.width > defaultItemSize.width) {
+            pageThumbnailSize = defaultItemSize
+        } else if (pageThumbnailSize.width == defaultItemSize.width) {
+            pageThumbnailSize = NSSize(width: defaultItemSize.width*0.5, height: defaultItemSize.height*0.5)
+        }
+        
+        collectionView.reloadData()
+        collectionView.selectionIndexPaths = indexpaths
+    }
+    
+    @objc public func copyMenuItemAciton() {
+        if IAPProductsManager.default().isAvailableAllFunction() == false {
+            let winC = KMPurchaseCompareWindowController.sharedInstance()
+            winC?.showWindow(nil)
+            return
+        }
+        KMNThumbnailManager.manager.copyPages = []
+
+        let indexpaths = collectionView.selectionIndexPaths
+        for indexpath in indexpaths.sorted() {
+            guard let page = showDocument?.page(at: UInt(indexpath.item)).copy() as? CPDFPage else {
+                continue
+            }
+            
+            KMNThumbnailManager.manager.copyDocument.append(showDocument ?? CPDFDocument())
+            KMNThumbnailManager.manager.copyPages.append(page)
+        }
+    }
+    
+    @objc public func pastMenuItemAciton() {
+        if IAPProductsManager.default().isAvailableAllFunction() == false {
+            let winC = KMPurchaseCompareWindowController.sharedInstance()
+            winC?.showWindow(nil)
+            return
+        }
+        
+        let selectedIndexPaths = collectionView.selectionIndexPaths
+
+        var pastIndex = 1
+        if(selectedIndexPaths.count > 0) {
+            let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
+            pastIndex = maxmumIndexPath?.item ?? 1
+        }
+        
+        var indexpaths: Set<IndexPath> = []
+        let copyPages = KMNThumbnailManager.manager.copyPages
+        let page = copyPages.first
+        if page?.document == showDocument {
+            for (i, page) in copyPages.enumerated() {
+                let zCopyPage = page.copy() as? CPDFPage
+                if(zCopyPage != nil) {
+                    showDocument?.insertPageObject(zCopyPage, at: UInt(pastIndex+i))
+                    indexpaths.insert(IndexPath(item: pastIndex+i, section: 0))
+                }
+            }
+        } else {
+            if let pasteDocument = page?.document {
+                var indexs: IndexSet = IndexSet()
+                for (i, _) in copyPages.enumerated() {
+                    indexs.insert(i)
+                    indexpaths.insert(IndexPath(item: pastIndex+i, section: 0))
+                }
+                showDocument?.importPages(indexs, from: pasteDocument, at: UInt(pastIndex))
+            }
+        }
+        refreshDatas()
+        collectionView.reloadData()
+        collectionView.selectionIndexPaths = indexpaths
+    }
+
+    @objc public func cutMenuItemAciton() {
+        if IAPProductsManager.default().isAvailableAllFunction() == false {
+            let winC = KMPurchaseCompareWindowController.sharedInstance()
+            winC?.showWindow(nil)
+            return
+        }
+        
+        let indexpaths = collectionView.selectionIndexPaths
+        for indexpath in indexpaths.sorted() {
+            guard let page = showDocument?.page(at: UInt(indexpath.item)).copy() as? CPDFPage else {
+                continue
+            }
+            
+            KMNThumbnailManager.manager.copyDocument.append(showDocument ?? CPDFDocument())
+            KMNThumbnailManager.manager.copyPages.append(page)
+            
+            showDocument?.removePage(at: UInt(indexpath.item))
+            refreshDatas()
+            collectionView.reloadData()
+        }
+    }
+    
+    @objc public func deleteMenuItemAciton() {
+        if IAPProductsManager.default().isAvailableAllFunction() == false {
+            let winC = KMPurchaseCompareWindowController.sharedInstance()
+            winC?.showWindow(nil)
+            return
+        }
+        let indexpaths = collectionView.selectionIndexPaths
+        for indexpath in indexpaths.sorted() {
+          
+            showDocument?.removePage(at: UInt(indexpath.item))
+            refreshDatas()
+            collectionView.reloadData()
+        }
+    }
+    
+    @objc func sharePageItemAction(menuItem:NSMenuItem) {
+        if IAPProductsManager.default().isAvailableAllFunction() == false {
+            let winC = KMPurchaseCompareWindowController.sharedInstance()
+            winC?.showWindow(nil)
+            return
+        }
+        let indexpaths = collectionView.selectionIndexPaths
+
+        let doucument = self.showDocument
+        let filename : String = doucument?.documentURL.lastPathComponent ?? ""
+        let folderPath = (NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(filename)) ?? ""
+        
+        try? FileManager.default.removeItem(atPath: folderPath)
         
+        let pdfdocument = CPDFDocument()
+        let ret = pdfdocument?.importPages(indexpathsToIndexs(indexpaths: indexpaths), from: doucument, at: 0) ?? false
+        let url = URL(fileURLWithPath: folderPath)
+        if ret {
+            let success = pdfdocument?.write(toFile: folderPath)
+            let represent = menuItem.representedObject as? NSSharingService
+            represent?.perform(withItems: [url])
+        }
+    }
+
+    @objc public func displayPageSizeAction() {
+        let indexpaths = collectionView.selectionIndexPaths
+        isShowPageSize = !isShowPageSize
+        collectionView.selectionIndexPaths = indexpaths
     }
 
 }

+ 438 - 0
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailBaseViewController+Action.swift

@@ -0,0 +1,438 @@
+//
+//  KMMainViewController+Action.swift
+//  PDF Reader Pro
+//
+//  Created by wanjun on 2022/12/15.
+//
+
+import Foundation
+
+extension KMNThumbnailBaseViewController {
+    private func fileNameWithSelectedPages(_ itemIndexes: IndexSet) -> String {
+        var pagesName = ""
+        if (itemIndexes.count > 1) {
+            pagesName.append(" pages")
+        } else {
+            pagesName.append(" page")
+        }
+        
+        let docmentName = showDocument?.documentURL.deletingPathExtension().lastPathComponent ?? ""
+        let tFileName = String(format: "%@ %@", pagesName,KMNTools.parseIndexSet(indexSet: itemIndexes))
+        return String(format: "%@%@", docmentName,tFileName)
+    }
+    
+    public func selectPages(with array: [Int]) {
+        var selectIndexPaths: Set<IndexPath> = []
+
+        for i in 0..<(showDocument?.pageCount ?? 0) {
+            if array.contains(Int(i)) {
+                selectIndexPaths.insert(IndexPath(item: Int(i), section: 0))
+            }
+        }
+
+        collectionView.selectionIndexPaths = selectIndexPaths
+
+        if selectIndexPaths.isEmpty { return }
+        
+        let firstIndexPath = selectIndexPaths.first
+        collectionView.scrollToItems(at: [firstIndexPath ?? IndexPath(item: 0, section: 0)], scrollPosition: .top)
+    }
+    
+   public func indexpathsToIndexs(indexpaths: Set<IndexPath>) -> IndexSet {
+        var indexs = IndexSet()
+        for indexPath in indexpaths {
+            indexs.insert(indexPath.item)
+        }
+        return indexs
+    }
+    
+    public func indexsToIndexpaths(indexs: IndexSet) -> Set<IndexPath> {
+        var indexpaths = Set<IndexPath>()
+        for index in indexs {
+            indexpaths.insert(IndexPath(item: index, section: 0))
+        }
+        return indexpaths
+    }
+    
+    public func insertFormPDF(insertPages: [CPDFPage],pageDex:Int) {
+        var pageIndexDex: Int = pageDex
+        var indexpaths = Set<IndexPath>()
+        for page in insertPages {
+            showDocument?.insertPageObject(page, at: UInt(pageIndexDex))
+            indexpaths.insert(IndexPath(item: pageIndexDex, section: 0))
+            pageIndexDex += 1
+        }
+        
+        collectionView.scrollToItems(at: indexpaths, scrollPosition: .centeredVertically)
+        
+        //        (currentUndoManager?.prepare(withInvocationTarget: self) as KMNThumbnailBaseViewController).deletePDFPages(indexpaths: indexpaths, scroIndex: pageDex)
+        
+    }
+    
+    public func deletePDFPages(indexpaths:Set<IndexPath>,scroIndex:Int) {
+        collectionView.reloadData()
+        collectionView.scrollToItems(at: [IndexPath(item: scroIndex, section: 0)], scrollPosition: .centeredVertically)
+        
+    }
+    
+    public func rotatePages(indexPaths: Set<IndexPath>, rotateAngle: Int) {
+        var tIndexPaths: Set<IndexPath> = []
+        tIndexPaths = indexPaths
+        for targetIndexPath in indexPaths {
+            if let page = showDocument?.page(at: UInt(targetIndexPath.item)) {
+                var pageRotate = page.rotation + rotateAngle
+                if(pageRotate  == -90) {
+                    pageRotate = 270
+                } else if (pageRotate == 450) {
+                    pageRotate = 90
+
+                }
+                page.rotation = pageRotate
+                
+                let cellView = collectionView.item(at: targetIndexPath) as? KMNThumbnailCollectionViewItem
+                if(cellView != nil) {
+                    cellView?.thumbnailMode.removeCacheImage()
+                }
+            }
+        }
+        
+        collectionView.reloadItems(at: tIndexPaths) // Ensure correct type conversion
+        collectionView.selectionIndexPaths = tIndexPaths
+
+    }
+    
+    public func reversePages(indexs: IndexSet) {
+        if let doc = showDocument {
+            var theIdxs = indexs
+            var res = false
+            for _ in 0 ..< indexs.count {
+                guard let first = theIdxs.first else {
+                    break
+                }
+                guard let last = theIdxs.last else {
+                    break
+                }
+                if first == last {
+                    break
+                }
+                res = doc.exchangePage(at: UInt(first), withPageAt: UInt(last))
+                if res {
+                    theIdxs.remove(first)                    
+                    theIdxs.remove(last)
+                   
+                }
+            }
+            if res {
+                refreshDatas()
+                let selected_indexpaths = self.indexsToIndexpaths(indexs: indexs)
+
+                collectionView.reloadItems(at: selected_indexpaths)
+                
+                collectionView.selectionIndexPaths = selected_indexpaths
+            }
+        }
+    }
+    
+    public func replacePages(of targetIndexpaths: Set<IndexPath>, with documents: [CPDFDocument]) {
+        if (targetIndexpaths.count == 0 || documents.count == 0) {
+            KMPrint("replace invalid.")
+            return
+        }
+        var index = targetIndexpaths.sorted().first!.item
+        var tIndexPaths: Set<IndexPath> = []
+        
+        var indexSet = indexpathsToIndexs(indexpaths: targetIndexpaths)
+        
+        showDocument?.removePage(at: indexSet)
+
+        for document in documents {
+            for i in 0 ..< document.pageCount {
+                let page = document.page(at: i)
+                self.showDocument?.insertPageObject(page, at: UInt(index))
+                tIndexPaths.insert(IndexPath(item: index, section: 0))
+                index += 1
+            }
+            thumbnailBaseViewDelegate?.insertPDFThumbnailViewControlle?(pageEditVC: self, pdfDocment: document)
+        }
+        
+        refreshDatas()
+
+        collectionView.reloadData()
+        
+        collectionView.selectionIndexPaths = tIndexPaths
+
+    }
+    
+    public func deletePages(indexpaths:Set<IndexPath>) {
+        var changeIndex:IndexSet = []
+        var tIndexPaths: Set<IndexPath> = []
+        tIndexPaths = indexpaths
+
+        for targetIndexPath in tIndexPaths {
+            changeIndex.insert(targetIndexPath.item)
+            
+            let cellView = collectionView.item(at: targetIndexPath) as? KMNThumbnailCollectionViewItem
+            if(cellView != nil) {
+                cellView?.thumbnailMode.removeCacheImage()
+            }
+
+        }
+        showDocument?.removePage(at: changeIndex)
+        refreshDatas()
+        collectionView.deleteItems(at: tIndexPaths)
+    }
+    
+    public func movePages(pages:[CPDFPage],destinationDex:Int) {
+        var destinationIndex = destinationDex
+   
+        for dragPage in dragLocalityPages {
+            let dragIndex = dragPage.pageIndex()
+            if destinationIndex > dragIndex {
+                destinationIndex -= 1
+                showDocument?.movePage(at: dragIndex, withPageAt: UInt(destinationIndex))
+            } else {
+                showDocument?.movePage(at: dragIndex, withPageAt: UInt(destinationIndex))
+            }
+            destinationIndex += 1
+        }
+        
+        var selectArray:[Int] = []
+        for dragPage in dragLocalityPages {
+            let dragIndex = dragPage.pageIndex()
+            selectArray.append(Int(dragIndex))
+        }
+        
+        refreshDatas()
+        collectionView.reloadData()
+        self.selectPages(with: selectArray)
+    }
+    
+    public func insertFromFilePath(fileNames:[String],formDex:Int,indexDex:UInt,selectIndexs:[Int],completionBlock:@escaping ([Int])->Void)-> Void {
+        let path = fileNames[formDex]
+        var insertDex = indexDex
+        var tSelectIndex = selectIndexs
+        
+        let pathExtension = URL(fileURLWithPath: path).pathExtension.lowercased()
+        if pathExtension == "pdf", let pdf = CPDFDocument(url: URL(fileURLWithPath: path)) {
+            if pdf.isLocked {
+                KMNBaseWindowController.checkPassword(url: pdf.documentURL, type: .owner) { success, resultPassword in
+                    if (resultPassword.isEmpty == false) {
+                        pdf.unlock(withPassword: resultPassword)
+                        
+                        for i in 0 ..< pdf.pageCount {
+                            let insertPage = pdf.page(at: i)
+                            self.showDocument?.insertPageObject(insertPage, at: insertDex)
+                            tSelectIndex.append(Int(insertDex))
+                            insertDex += 1
+                        }
+                        
+                        var tFormDex = formDex
+                        tFormDex += 1
+                        self.thumbnailBaseViewDelegate?.insertPDFThumbnailViewControlle?(pageEditVC: self, pdfDocment: pdf)
+                        if(tFormDex < fileNames.count) {
+                            return self.insertFromFilePath(fileNames: fileNames, formDex: tFormDex, indexDex: indexDex, selectIndexs: tSelectIndex,completionBlock: completionBlock)
+                        } else {
+                            return completionBlock(tSelectIndex)
+                        }
+
+                    }
+                }
+            } else {
+                for i in 0 ..< pdf.pageCount {
+                    let insertPage = pdf.page(at: i)
+                    showDocument?.insertPageObject(insertPage ?? CPDFPage(), at: insertDex)
+                    tSelectIndex.append(Int(insertDex))
+                    insertDex += 1
+                }
+                var tFormDex = formDex
+                tFormDex += 1
+                self.thumbnailBaseViewDelegate?.insertPDFThumbnailViewControlle?(pageEditVC: self, pdfDocment: pdf)
+                if(tFormDex < fileNames.count) {
+                    return self.insertFromFilePath(fileNames: fileNames, formDex: tFormDex, indexDex: indexDex, selectIndexs: tSelectIndex,completionBlock: completionBlock)
+                } else {
+                    return completionBlock(tSelectIndex)
+                }
+                
+            }
+        } else if supportDragFileTypes().contains(pathExtension) {
+            if KMConvertPDFManager.supportImages().contains(pathExtension) {
+                if let image = NSImage(contentsOfFile: path) {
+                     _ = showDocument?.km_insertPage(image.size, withImage: path, at: indexDex)
+                    tSelectIndex.append(Int(insertDex))
+                    insertDex += 1
+                }
+                
+                var tFormDex = formDex
+                tFormDex += 1
+                if(tFormDex < fileNames.count) {
+                    return self.insertFromFilePath(fileNames: fileNames, formDex: tFormDex, indexDex: indexDex, selectIndexs: tSelectIndex,completionBlock: completionBlock)
+                } else {
+                    return completionBlock(tSelectIndex)
+                }
+                
+            } else {
+                convertOffice(filePath: path) { convertPDFPath in
+                    if (convertPDFPath != nil) {
+                        let pathExtension = URL(fileURLWithPath: convertPDFPath!).pathExtension.lowercased()
+                        if pathExtension == "pdf", let pdf = CPDFDocument(url: URL(fileURLWithPath: convertPDFPath!)) {
+                            for i in 0 ..< pdf.pageCount {
+                                let insertPage = pdf.page(at: i)
+                                self.showDocument?.insertPageObject(insertPage, at: insertDex)
+                                tSelectIndex.append(Int(insertDex))
+                                insertDex += 1
+                            }
+                            self.thumbnailBaseViewDelegate?.insertPDFThumbnailViewControlle?(pageEditVC: self, pdfDocment: pdf)
+
+                            var tFormDex = formDex
+                            tFormDex += 1
+                            if(tFormDex < fileNames.count) {
+                                return self.insertFromFilePath(fileNames: fileNames, formDex: tFormDex, indexDex: indexDex, selectIndexs: tSelectIndex,completionBlock: completionBlock)
+                            } else {
+                                return completionBlock(tSelectIndex)
+                            }
+                            
+                        }
+                    }
+                }
+            }
+            
+        }
+    }
+    
+    private func convertOffice(filePath: String, completionBlock:@escaping (String?)->Void) -> Void {
+        let today = Date()
+        let dateFormatter = DateFormatter()
+        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
+        let dateString = dateFormatter.string(from: today)
+
+        let folderPath = "convertToPDF_office_" + dateString + "." + "pdf"
+
+        let savePath: String? = folderPath.kUrlToPDFFolderPath() as String
+        
+        KMConvertPDFManager.convertFile(filePath, savePath: savePath!) { success, errorDic in
+            if errorDic != nil || !success || !FileManager.default.fileExists(atPath: savePath!) {
+                
+                if FileManager.default.fileExists(atPath: savePath!) {
+                    try?FileManager.default.removeItem(atPath: savePath!)
+                }
+                let alert = NSAlert.init()
+                alert.alertStyle = .critical
+                var infoString = ""
+                if errorDic != nil {
+                    for key in (errorDic! as Dictionary).keys {
+                        infoString = infoString.appendingFormat("%@\n", errorDic![key] as! CVarArg)
+                    }
+                }
+                alert.informativeText = NSLocalizedString("Please install Microsoft Office to create PDFs from Office files", comment: "")
+                alert.messageText = NSLocalizedString("Failed to Create PDF", comment: "")
+                alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
+                alert.runModal()
+                completionBlock(nil)
+                return
+            }
+            
+            if !savePath!.isPDFValid() {
+                let alert = NSAlert()
+                alert.alertStyle = .critical
+                alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
+                alert.runModal()
+                completionBlock(nil)
+                return
+            }
+            completionBlock(savePath)
+        }
+        
+    }
+    
+    public func extractPages(indexpaths: Set<IndexPath>, oneDocumentPerPage: Bool, callback: @escaping KMResultBlock) {
+        let pageIndexs = self.indexpathsToIndexs(indexpaths: indexpaths)
+        let oneDocument = !oneDocumentPerPage
+        let document = self.showDocument!
+        /// 提取的页面
+        var extractPages: Array<CPDFPage> = []
+        for i in pageIndexs {
+            extractPages.append(document.page(at: UInt(i)))
+        }
+        
+        if (oneDocument) { /// 提取为一个文档
+            var fileName = document.documentURL.deletingPathExtension().lastPathComponent
+            fileName.append(" pages ")
+            fileName.append(KMNTools.newParseSelectedIndexs(selectedIndex: pageIndexs.sorted()))
+            fileName.append(".pdf")
+            NSPanel.savePanel(self.view.window!, true) { panel in
+                panel.nameFieldStringValue = fileName
+            } completion: { response, url, isOpen in
+                if (response != .OK) {
+                    callback(.cancel)
+                    return
+                }
+                
+                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
+                    DispatchQueue.global().async {
+                        var success = false
+                        let pdf = CPDFDocument.init()
+                        success = pdf!.extractAsOneDocument(withPages: extractPages, savePath: url!.path)
+                        DispatchQueue.main.async {
+                            if (success == false) {
+                                callback(.failure)
+                                return
+                            }
+                            
+                            if (isOpen == false) {
+                                NSWorkspace.shared.activateFileViewerSelecting([url!])
+                            } else {
+                                NSDocumentController.shared.km_safe_openDocument(withContentsOf: url!, display: true) { _, _, _ in
+                                }
+                            }
+                            callback(.success, [url!])
+                        }
+                    }
+                }
+            }
+            return
+        } else {
+            let panel = NSOpenPanel()
+            panel.canChooseFiles = false
+            panel.canChooseDirectories = true
+            panel.canCreateDirectories = true
+            panel.allowsMultipleSelection = false
+            panel.beginSheetModal(for: self.view.window!) {  response in
+                if response != .OK {
+                    callback(.cancel)
+                    return
+                }
+                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
+                    let outputURL = panel.url
+                    DispatchQueue.global().async {
+                        let folderName = String((document.documentURL.lastPathComponent.split(separator: ".")[0])) + "_extract"
+                        
+                        var filePath = URL(fileURLWithPath: outputURL!.path).appendingPathComponent(folderName).path
+                        var i = 1
+                        let testFilePath = filePath
+                        while FileManager.default.fileExists(atPath: filePath) {
+                            filePath = testFilePath + "\(i)"
+                            i += 1
+                        }
+                        
+                        try? FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: false, attributes: nil)
+                        
+                        var successArray: [URL]?
+                        successArray = document.extractPerPageDocument(withPages: extractPages, folerPath: filePath)
+                        
+                        DispatchQueue.main.async {
+                            if successArray!.count == 0 {
+                                callback(.failure)
+                                return
+                            }
+                            NSWorkspace.shared.activateFileViewerSelecting(successArray!)
+                                
+                            callback(.success, successArray ?? NSURL())
+                        }
+                    }
+                }
+            }
+        }
+        
+    }
+    
+}

+ 118 - 121
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailBaseViewController.swift

@@ -15,12 +15,12 @@ import Cocoa
 
 internal let kmnThumLocalForDraggedTypes = NSPasteboard.PasteboardType(rawValue: "kmnThumLocalForDraggedTypes")
 
-class KMNThumbnailBaseViewController: NSViewController,NSCollectionViewDelegate, NSCollectionViewDataSource,NSCollectionViewDelegateFlowLayout {
+class KMNThumbnailBaseViewController: KMNBaseViewController,NSCollectionViewDelegate, NSCollectionViewDataSource,NSCollectionViewDelegateFlowLayout {
     
     weak open var thumbnailBaseViewDelegate: KMNThumbnailBaseViewDelegate?
     
     @IBOutlet var backViewBox: NSBox!
-    @IBOutlet var collectionView: NSCollectionView!
+    @IBOutlet var collectionView: KMNThumbnailCollectionView!
     
     let subTitleHeight: CGFloat = 20.0
     
@@ -66,17 +66,19 @@ class KMNThumbnailBaseViewController: NSViewController,NSCollectionViewDelegate,
     }
     
     public var isAdjustWidth:Bool = false
-    
+        
     public var isShowPageSize:Bool = false {
         didSet {
             if oldValue != isShowPageSize {
                 var pageSize = pageThumbnailSize
                 if(isShowPageSize) {
-                    pageSize.height -= subTitleHeight
-                } else {
                     pageSize.height += subTitleHeight
+                } else {
+                    pageSize.height -= subTitleHeight
+
                 }
                 pageThumbnailSize = pageSize
+                collectionView.reloadData()
             }
         }
     }
@@ -86,8 +88,9 @@ class KMNThumbnailBaseViewController: NSViewController,NSCollectionViewDelegate,
             collectionView.reloadData()
         }
     }
+    public let defaultItemSize = NSMakeSize(185.0, 260)
     
-    var dragLocalityIndexPaths: Set<IndexPath> = []
+    var dragLocalityPages: [CPDFPage] = []
     
     deinit {
         thumbnailBaseViewDelegate = nil
@@ -120,14 +123,6 @@ class KMNThumbnailBaseViewController: NSViewController,NSCollectionViewDelegate,
     override func viewDidLoad() {
         super.viewDidLoad()
         
-        thumbnails = []
-        if currentDocument != nil {
-            for i in 0 ... currentDocument!.pageCount {
-                let thumbnail = KMNThumbnail.init(document: currentDocument!, currentPageIndex: Int(i))
-                thumbnails.append(thumbnail)
-            }
-        }
-        
         collectionView.delegate = self
         collectionView.dataSource = self
         collectionView.isSelectable = true //支持拖拽需设置未True
@@ -135,56 +130,33 @@ class KMNThumbnailBaseViewController: NSViewController,NSCollectionViewDelegate,
         
         collectionView.register(KMNThumbnailCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "thumbnailCollectionViewItem"))
         
-        collectionView.registerForDraggedTypes(NSFilePromiseReceiver.readableDraggedTypes.map { NSPasteboard.PasteboardType($0) })
-        
-        collectionView.registerForDraggedTypes([kmnThumLocalForDraggedTypes, .fileURL,.string,.pdf])
+        collectionView.registerForDraggedTypes([.fileURL])
+        collectionView.setDraggingSourceOperationMask(.every, forLocal: false)
+        collectionView.setDraggingSourceOperationMask(.every, forLocal: true)
+
+        refreshDatas()
     }
     
     public func exitCurrentView() {
         thumbnailBaseViewDelegate?.clickThumbnailViewControlle?(pageEditVC: self, currentIndex: clickPageIndex)
     }
     
-    private func supportDragFileTypes()->[String] {
-        let supportFiles = KMTools.pdfExtensions + KMConvertPDFManager.supportFileType()
+    public func supportDragFileTypes()->[String] {
+        let supportFiles = KMNConvertTool.pdfExtensions + KMConvertPDFManager.supportFileType()
 
         return supportFiles
     }
     
-    private func fileNameWithSelectedPages(_ itemIndexes: IndexSet) -> String {
-        var pagesName = ""
-        if (itemIndexes.count > 1) {
-            pagesName.append(" pages")
-        } else {
-            pagesName.append(" page")
+    public func refreshDatas() {
+        thumbnails = []
+        if currentDocument != nil {
+            for i in 0 ... currentDocument!.pageCount {
+                let thumbnail = KMNThumbnail.init(document: currentDocument!, currentPageIndex: Int(i))
+                thumbnails.append(thumbnail)
+            }
         }
-        
-        let docmentName = currentDocument?.documentURL.deletingPathExtension().lastPathComponent ?? ""
-        let tFileName = String(format: "%@ %@", pagesName,KMNTools.parseIndexSet(indexSet: itemIndexes))
-        return String(format: "%@%@", docmentName,tFileName)
     }
-    
-    public func insertFormPDF(insertPages: [CPDFPage],pageDex:Int) {
-        var pageIndexDex: Int = pageDex
-        var indexpaths = Set<IndexPath>()
-        for page in insertPages {
-            currentDocument?.insertPageObject(page, at: UInt(pageIndexDex))
-            indexpaths.insert(IndexPath(item: pageIndexDex, section: 0))
-            pageIndexDex += 1
-        }
-                
-        collectionView.scrollToItems(at: indexpaths, scrollPosition: .centeredVertically)
-        
-//        (currentUndoManager?.prepare(withInvocationTarget: self) as KMNThumbnailBaseViewController).deletePDFPages(indexpaths: indexpaths, scroIndex: pageDex)
 
-    }
-    
-    public func deletePDFPages(indexpaths:Set<IndexPath>,scroIndex:Int) {
-        collectionView.reloadData()
-        collectionView.scrollToItems(at: [IndexPath(item: scroIndex, section: 0)], scrollPosition: .centeredVertically)
-        
-    }
-    
-    
     // MARK: - NSCollectionViewDataSource
     func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
         return thumbnails.count
@@ -235,93 +207,118 @@ class KMNThumbnailBaseViewController: NSViewController,NSCollectionViewDelegate,
     }
     
     //MARK: - NSCollectionViewDelegate
-    
-    func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set<IndexPath>, with event: NSEvent) -> Bool {
-        return IAPProductsManager.default().isAvailableAllFunction()
-    }
-    
-    func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool {
-        let data: Data = try! NSKeyedArchiver.archivedData(withRootObject: indexPaths, requiringSecureCoding: true)
-        pasteboard.declareTypes([kmnThumLocalForDraggedTypes], owner: self)
-        pasteboard.setData(data, forType: kmnThumLocalForDraggedTypes)
+    func collectionView(_ collectionView: NSCollectionView,
+                        writeItemsAt indexPaths: Set<IndexPath>,
+                        to pasteboard: NSPasteboard) -> Bool {
+        if IAPProductsManager.default().isAvailableAllFunction() == false {
+            return false
+        }
+        
+        var docmentName = currentDocument?.documentURL.lastPathComponent.deletingPathExtension ?? ""
+        let pagesName = indexPaths.count > 1 ? " pages" : " page"
+        var tFileName = pagesName + KMNTools.parseIndexPathsSet(indexSets: collectionView.selectionIndexPaths)
+        if tFileName.count > 50 {
+            tFileName = String(tFileName.prefix(50))
+        }
+        
+        pasteboard.declareTypes([.fileURL], owner: self)
+        let writePDFDocument = CPDFDocument()
+        
+        for indexPath in indexPaths {
+            let row = indexPath.item
+            if let copyPage = currentDocument?.page(at: UInt(row)) as? CPDFPage {
+                writePDFDocument?.insertPageObject(copyPage, at: writePDFDocument?.pageCount ?? 0)
+            }
+        }
         
-        dragLocalityIndexPaths.removeAll()
-        dragLocalityIndexPaths = indexPaths
-        return true
+        var cachesDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
+        cachesDir =  cachesDir.appendingPathComponent("PageEdit_Pasteboard")
+        let fileManager = FileManager.default
+        if !fileManager.fileExists(atPath: cachesDir.path) {
+            try? FileManager.default.createDirectory(atPath: cachesDir.path, withIntermediateDirectories: true, attributes: nil)
+        }
+        docmentName = "\(docmentName)\(tFileName)"
+        if docmentName.count > 50 {
+            docmentName = String(docmentName.prefix(50))
+        }
+        
+        let filePathURL = cachesDir.appendingPathComponent(docmentName).appendingPathExtension("pdf")
+        let success = writePDFDocument?.write(to: filePathURL, isSaveFontSubset:false)
+        if success == true {
+            pasteboard.setPropertyList([filePathURL.path], forType: .fileURL)
+            return true
+        } else {
+            return false
+        }
     }
     
-    func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {
+    func collectionView(_ collectionView: NSCollectionView,
+                        draggingSession session: NSDraggingSession,
+                        willBeginAt screenPoint: NSPoint,
+                        forItemsAt indexPaths: Set<IndexPath>) {
+        let sortedIndexPaths = indexPaths.sorted { (ip1, ip2) -> Bool in
+            if ip1.section == ip2.section {
+                return ip1.item < ip2.item
+            }
+            return ip1.section < ip2.section
+        }
+        dragLocalityPages = []
+        for fromIndexPath in sortedIndexPaths {
+            let page = thumbnails[fromIndexPath.item].thumbnaiPage
+            if(page != nil) {
+                dragLocalityPages.append(page!)
+            }
+        }
+    }
 
+    func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {
         let pboard = draggingInfo.draggingPasteboard
-        if (pboard.availableType(from: [kmnThumLocalForDraggedTypes]) != nil) {
-            return .move
-        } else if (pboard.availableType(from: [.localDraggedTypes]) != nil) {
         
-            return .move
-        } else if ((pboard.availableType(from: [.fileURL])) != nil) {
-            guard let pbItems = pboard.pasteboardItems else {
-                return NSDragOperation(rawValue: 0)
+        if dragLocalityPages.count != 0 {
+            if proposedDropOperation.pointee == .on {
+                proposedDropOperation.pointee = .before
             }
-            let allowedFileTypes = supportDragFileTypes()
-            
-            var hasValidFile = false
-            for item in pbItems {
-                guard let data = item.string(forType: .fileURL), let fileUrl = URL(string: data) else {
-                    continue
-                }
-                let type = fileUrl.pathExtension.lowercased()
-                if (allowedFileTypes.contains(type)) {
-                    hasValidFile = true
-                    break
+            return .move
+        } else if let availableType = pboard.availableType(from: [.fileURL]), availableType == .fileURL {
+            if let fileNames = pboard.propertyList(forType: .fileURL) as? [String], fileNames.count >= 1 {
+                let path = fileNames.first!
+                let pathExtension = URL(fileURLWithPath: path).pathExtension.lowercased()
+                if pathExtension == "pdf" || supportDragFileTypes().contains(pathExtension) {
+                    return .copy
                 }
             }
-            
-            if (!hasValidFile) {
-                return NSDragOperation(rawValue: 0)
-            }
         }
-        
-        return .generic
+        return []
     }
-    
-    func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {
-        let result = false
-        if !IAPProductsManager.default().isAvailableAllFunction() {
-            return result
-        }
+
+    func collectionView(_ collectionView: NSCollectionView,
+                        acceptDrop draggingInfo: NSDraggingInfo,
+                        indexPath: IndexPath,
+                        dropOperation: NSCollectionView.DropOperation) -> Bool {
         let pboard = draggingInfo.draggingPasteboard
-        if (pboard.availableType(from: [kmnThumLocalForDraggedTypes]) != nil) {
-            
-        } else if (pboard.availableType(from: [.localDraggedTypes]) != nil) {
-        
-        } else if ((pboard.availableType(from: [.fileURL])) != nil) {
-         
-            guard let pbItems = pboard.pasteboardItems else {
-                return false
-            }
+        if dragLocalityPages.count != 0 {
+            movePages(pages: dragLocalityPages, destinationDex: indexPath.item)
+            return true
+        } else if let availableType = pboard.availableType(from: [.fileURL]), availableType == .fileURL {
+            let index = indexPath.item
             
-            //获取url
-            var array: [URL] = []
-            for item in pbItems {
-                guard let data = item.string(forType: .fileURL), let url = URL(string: data) else {
-                    continue
-                }
-                let allowedFileTypes = supportDragFileTypes()
-                let type = url.pathExtension.lowercased()
-                if (allowedFileTypes.contains(type)) {
-                    array.append(url)
+            if let fileNames = pboard.propertyList(forType: .fileURL) as? [String] {
+                insertFromFilePath(fileNames: fileNames, formDex: 0, indexDex: UInt(index), selectIndexs: []) { zSelectIndexs in
+                    self.refreshDatas()
+                    self.selectPages(with: zSelectIndexs)
                 }
+                
+                return true
             }
-            
         }
-
-        return true
-    }
-    
-    func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, dragOperation operation: NSDragOperation) {
-        print("6")
-        dragLocalityIndexPaths = []
+        return false
     }
 
+    func collectionView(_ collectionView: NSCollectionView,
+                        draggingSession session: NSDraggingSession,
+                        endedAt screenPoint: NSPoint,
+                        dragOperation operation: NSDragOperation) {
+        dragLocalityPages = []
+    }
 
 }

+ 1 - 1
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailBaseViewController.xib

@@ -31,7 +31,7 @@
                                     <rect key="frame" x="0.0" y="0.0" width="861" height="501"/>
                                     <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                     <subviews>
-                                        <collectionView id="zKK-EM-MTi">
+                                        <collectionView id="zKK-EM-MTi" customClass="KMNThumbnailCollectionView" customModule="PDF_Reader_Pro" customModuleProvider="target">
                                             <rect key="frame" x="0.0" y="0.0" width="861" height="158"/>
                                             <autoresizingMask key="autoresizingMask" widthSizable="YES"/>
                                             <collectionViewFlowLayout key="collectionViewLayout" minimumInteritemSpacing="10" minimumLineSpacing="10" id="s08-Bd-SKp">

+ 49 - 0
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailCollectionView.swift

@@ -0,0 +1,49 @@
+//
+//  KMNCollectionView.swift
+//  PDF Reader Pro
+//
+//  Created by 丁林圭 on 2024/10/27.
+//
+
+import Cocoa
+
+class KMNThumbnailCollectionView: NSCollectionView {
+    var menuClickedAction: ((_ clickPoint: NSPoint) -> NSMenu)?
+
+
+    override func draw(_ dirtyRect: NSRect) {
+        super.draw(dirtyRect)
+
+        // Drawing code here.
+    }
+    
+    override func menu(for event: NSEvent) -> NSMenu? {
+        let point = event.locationInWindow
+        let rightIndex = indexPathForItem(at: convert(point, from: nil))
+        if rightIndex != nil {
+            let cellView = item(at: rightIndex!) as? KMNThumbnailCollectionViewItem
+            if(cellView != nil) {
+                if(cellView?.isSelected == true) {
+                    
+                } else {
+                    self.selectionIndexPaths = NSMutableSet() as! Set<IndexPath>
+                    var indexPaths: Set<IndexPath> = []
+                    indexPaths.insert(rightIndex!)
+                    self.selectionIndexPaths = indexPaths
+                }
+            } else {
+                self.selectionIndexPaths = NSMutableSet() as! Set<IndexPath>
+            }
+        } else {
+            self.selectionIndexPaths = NSMutableSet() as! Set<IndexPath>
+        }
+        
+        if menuClickedAction != nil {
+            let menu = menuClickedAction!(point)
+            return menu
+        }
+        
+        return super.menu(for: event)
+    }
+    
+}

+ 17 - 15
PDF Office/PDF Master/KMClass/KMNPDFPageEdit/KMNThumbnailView/KMNThumbnailCollectionViewItem.swift

@@ -20,12 +20,15 @@ class KMNThumbnailCollectionViewItem: NSCollectionViewItem {
             cardFileView.properties = ComponentCardFileProperty(folder: false,
                                                                 state: .normal,
                                                                 icon: NSImage.init(named: "KMNImageNameThumbnailPlaceImage"),
-                                                                text: String(format: "%d", thumbnailMode.pageIndex),
-                                                                subText: String(format: "%.0f x %.0f", thumbnailMode.pageSize.width, thumbnailMode.pageSize.height),
+                                                                text: String(format: "%d", (thumbnailMode.pageIndex+1)),
+                                                                subText: String(format: "%.0f x %.0fmm", thumbnailMode.pageSize.width, thumbnailMode.pageSize.height),
                                                                 markIcon:NSImage.init(named: "KMNImageNameThumbnailBookMark"))
-            
-            cardFileView.properties.propertyInfo.infoLabelHeight = 16.0
+            cardFileView.properties.isShowSubText = isShowFileSize
 
+            cardFileView.properties.propertyInfo.infoLabelHeight = 16.0
+            cardFileView.properties.isShowMarkIcon = thumbnailMode.isHoveBookMark
+            cardFileView.reloadData()
+            
             let maxThumCellWidth = self.view.frame.size.width - 32.0
             
             var maxThumCellHeight = self.view.frame.size.height
@@ -35,14 +38,18 @@ class KMNThumbnailCollectionViewItem: NSCollectionViewItem {
             maxThumCellHeight -= cardFileView.properties.propertyInfo.subLabelHeight
             
             maxThumCellHeight -= (cardFileView.properties.propertyInfo.topIconOffset + cardFileView.properties.propertyInfo.bottomOffset + cardFileView.properties.propertyInfo.topLabelOffset) //间隔
-            let orgPageHeight = thumbnailMode.pageSize.height
-            let orgPagewidth = thumbnailMode.pageSize.width
+            var orgPageHeight = thumbnailMode.pageSize.height
+            var orgPagewidth = thumbnailMode.pageSize.width
+            
+            if (thumbnailMode.thumbnaiPage?.rotation ?? 0) % 180 != 0 {
+                orgPageHeight = thumbnailMode.pageSize.width
+                orgPagewidth = thumbnailMode.pageSize.height
+            }
             
             let minimumValue = min(maxThumCellHeight/orgPageHeight, maxThumCellWidth/orgPagewidth)
             
-            let relCellHeight = thumbnailMode.pageSize.height * minimumValue
-            let relCellWidth = thumbnailMode.pageSize.width * minimumValue
-            cardFileView.properties.isShowMarkIcon = thumbnailMode.isHoveBookMark
+            let relCellHeight = orgPageHeight * minimumValue
+            let relCellWidth = orgPagewidth * minimumValue
 
             thumbnailMode.generateThumImage { image in
                 self.cardFileView.properties.propertyInfo.iconImageWidth = relCellWidth
@@ -64,12 +71,7 @@ class KMNThumbnailCollectionViewItem: NSCollectionViewItem {
         }
     }
     
-    public var isShowFileSize :Bool = false {
-        didSet {
-            cardFileView.properties.isShowSubText = isShowFileSize
-            cardFileView.reloadData()
-        }
-    }
+    public var isShowFileSize :Bool = false
 
     override func viewDidLoad() {
         super.viewDidLoad()

+ 13 - 0
PDF Office/PDF Master/KMClass/KMPDFViewController/KMPDFViewController.swift

@@ -450,8 +450,21 @@ extension KMPDFViewController: KMPDFToolbarControllerDelegate {
             pageEditViewController?.deletePageAction()
         } else if itemIdentifier == KMPDFToolbar_PageEdit_Reduce_Identifier {
             pageEditViewController?.zoomOutPageAction()
+            if(pageEditViewController?.canZoomOutPageSize() == false) {
+                toolbarManager.page_Reduce_Property.isDisabled = true
+            } else {
+                toolbarManager.page_Reduce_Property.isDisabled = false
+            }
+            controller.refreshSecondToolbarItemsState()
         } else if itemIdentifier == KMPDFToolbar_PageEdit_Increase_Identifier {
             pageEditViewController?.zoomInPageAction()
+            
+            if(pageEditViewController?.canZoomInPageSize() == false) {
+                toolbarManager.page_Increase_Property.isDisabled = true
+            } else {
+                toolbarManager.page_Increase_Property.isDisabled = false
+            }
+            controller.refreshSecondToolbarItemsState()
         }
         
         refreshToolbarView()

+ 2 - 2
PDF Office/PDF Master/KMClass/KMPDFViewController/Toolbar/KMPDFSecToolbarController.xib

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>

+ 9 - 9
PDF Office/PDF Master/KMClass/KMPDFViewController/Toolbar/Model/KMPDFToolbarManager.swift

@@ -27,16 +27,16 @@ class KMPDFToolbarManager: NSObject {
     var page_Insert_Clip_Property: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false, itemSelected: false, isDisabled: false, text: KMLocalizedString("From Clipboard"), identifier: KMPDFToolbar_PageEdit_InsertClip_Identifier)
     var page_Insert_Scanner_Property: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false, itemSelected: false, isDisabled: false, text: KMLocalizedString("From Scanner"), identifier: KMPDFToolbar_PageEdit_InsertScanner_Identifier)
 
-    var page_Extract_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true, buttonText: KMLocalizedString("Extract"), icon: NSImage(named: "pageEdit_extract"), identifier: KMPDFToolbar_PageEdit_Extract_Identifier)
-    var page_Replace_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true, buttonText: KMLocalizedString("Replace"), icon: NSImage(named: "pageEdit_replace"), identifier: KMPDFToolbar_PageEdit_Replace_Identifier)
-    var page_Split_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true,  buttonText: KMLocalizedString("Split"),icon: NSImage(named: "pageEdit_split"), identifier: KMPDFToolbar_PageEdit_Split_Identifier)
-    var page_Reverse_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true, buttonText: KMLocalizedString("Reverse"), icon: NSImage(named: "pageEdit_reverse"), identifier: KMPDFToolbar_PageEdit_Reverse_Identifier)
+    var page_Extract_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true, buttonText: KMLocalizedString("Extract"), icon: NSImage(named: "pageEdit_extract"), keepPressState: false, identifier: KMPDFToolbar_PageEdit_Extract_Identifier)
+    var page_Replace_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true, buttonText: KMLocalizedString("Replace"), icon: NSImage(named: "pageEdit_replace"), keepPressState: false, identifier: KMPDFToolbar_PageEdit_Replace_Identifier)
+    var page_Split_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true,  buttonText: KMLocalizedString("Split"),icon: NSImage(named: "pageEdit_split"), keepPressState: false, identifier: KMPDFToolbar_PageEdit_Split_Identifier)
+    var page_Reverse_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, showLeftIcon: true, buttonText: KMLocalizedString("Reverse"), icon: NSImage(named: "pageEdit_reverse"), keepPressState: false, identifier: KMPDFToolbar_PageEdit_Reverse_Identifier)
     
-    var page_LeftRotate_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_rotateLeft"), identifier: KMPDFToolbar_PageEdit_LeftRotate_Identifier)
-    var page_RightRotate_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_rotateRight"), identifier: KMPDFToolbar_PageEdit_RightRotate_Identifier)
-    var page_Delete_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_delete"), identifier: KMPDFToolbar_PageEdit_Delete_Identifier)
-    var page_Reduce_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_zoomout"), identifier: KMPDFToolbar_PageEdit_Reduce_Identifier)
-    var page_Increase_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_zoomin"), identifier: KMPDFToolbar_PageEdit_Increase_Identifier)
+    var page_LeftRotate_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_rotateLeft"), keepPressState: false,identifier: KMPDFToolbar_PageEdit_LeftRotate_Identifier)
+    var page_RightRotate_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_rotateRight"), keepPressState: false,identifier: KMPDFToolbar_PageEdit_RightRotate_Identifier)
+    var page_Delete_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_delete"), keepPressState: false,identifier: KMPDFToolbar_PageEdit_Delete_Identifier)
+    var page_Reduce_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_zoomout"), keepPressState: false,identifier: KMPDFToolbar_PageEdit_Reduce_Identifier)
+    var page_Increase_Property: ComponentButtonProperty = ComponentButtonProperty(type: .text_gray_opacity, size: .xs, onlyIcon: true, icon: NSImage(named: "pageEdit_zoomin"),keepPressState: false, identifier: KMPDFToolbar_PageEdit_Increase_Identifier)
  
     //MARK: -ToosView
     var toolsProperty: ComponentDropdownToolProperty = ComponentDropdownToolProperty(state: .normal, leftIcon: NSImage(named: "toolbar_Tools_select"), showDropdown: true)

+ 49 - 0
PDF Office/PDF Master/KMClass/Tools/Tool/KMNTools.swift

@@ -9,6 +9,55 @@ import Cocoa
 
 class KMNTools: NSObject {
     
+    class func newParseSelectedIndexs(selectedIndex: Array<Int>) -> String {
+        if (selectedIndex.count == 0) {
+            return ""
+        }
+        
+        if (selectedIndex.count == 1) {
+            return "\(selectedIndex.first!+1)"
+        }
+        
+        var newDatas: Array<Int> = []
+        for i in selectedIndex {
+            newDatas.append(i)
+        }
+        /// 排序
+        /// 根据id进行排序(升序)
+        newDatas.sort(){$0 < $1}
+        
+        var a: Int = 0
+        var b: Int = 0
+        var result: String? = nil
+        for i in newDatas {
+            if (result == nil) {
+                a = i
+                b = i
+                result = ""
+            } else {
+                if (i == b+1) {
+                    b = i
+                    if (i == newDatas.last) {
+                        result!.append(String(format: "%d-%d", a+1,b+1))
+                    }
+                } else {
+                    if (a == b) {
+                        result!.append(String(format: "%d,", a+1))
+                    } else {
+                        result!.append(String(format: "%d-%d,", a+1,b+1))
+                    }
+                    a = i
+                    b = i
+                    if (i == newDatas.last) {
+                        result!.append(String(format: "%d", a+1))
+                    }
+                }
+            }
+        }
+        
+        return result!
+    }
+    
     @objc class func parseIndexPathsSet(indexSets: Set<IndexPath>) -> String {
         var indexSet = IndexSet()
         for indeIndexPath in indexSets {

BIN
PDF Office/PDF Master/Source/default.metallib


+ 24 - 8
PDF Office/PDF Reader Pro.xcodeproj/project.pbxproj

@@ -607,9 +607,6 @@
 		9F1F82EA2935D02E0092C4B4 /* KMComboBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82E92935D02E0092C4B4 /* KMComboBox.swift */; };
 		9F1F82EB2935D02E0092C4B4 /* KMComboBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82E92935D02E0092C4B4 /* KMComboBox.swift */; };
 		9F1F82EC2935D02E0092C4B4 /* KMComboBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82E92935D02E0092C4B4 /* KMComboBox.swift */; };
-		9F1F82EE293609F60092C4B4 /* CPDFDocument+PageEditManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82ED293609F50092C4B4 /* CPDFDocument+PageEditManager.swift */; };
-		9F1F82EF293609F60092C4B4 /* CPDFDocument+PageEditManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82ED293609F50092C4B4 /* CPDFDocument+PageEditManager.swift */; };
-		9F1F82F0293609F60092C4B4 /* CPDFDocument+PageEditManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82ED293609F50092C4B4 /* CPDFDocument+PageEditManager.swift */; };
 		9F1F82F229373D6E0092C4B4 /* String+KMExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82F129373D6E0092C4B4 /* String+KMExtensions.swift */; };
 		9F1F82F329373D6E0092C4B4 /* String+KMExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82F129373D6E0092C4B4 /* String+KMExtensions.swift */; };
 		9F1F82F429373D6E0092C4B4 /* String+KMExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F1F82F129373D6E0092C4B4 /* String+KMExtensions.swift */; };
@@ -5747,9 +5744,18 @@
 		F3B7DFA42949C8E300333201 /* CPDFListView.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F3B7DFA32949C8E300333201 /* CPDFListView.xcassets */; };
 		F3B7DFA52949C8E300333201 /* CPDFListView.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F3B7DFA32949C8E300333201 /* CPDFListView.xcassets */; };
 		F3B7DFA62949C8E300333201 /* CPDFListView.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F3B7DFA32949C8E300333201 /* CPDFListView.xcassets */; };
+		F3C7984E2CD0F62A008A18E2 /* CPDFDocument+PageEditManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C7984D2CD0F629008A18E2 /* CPDFDocument+PageEditManager.swift */; };
+		F3C7984F2CD0F62A008A18E2 /* CPDFDocument+PageEditManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C7984D2CD0F629008A18E2 /* CPDFDocument+PageEditManager.swift */; };
+		F3C798502CD0F62A008A18E2 /* CPDFDocument+PageEditManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3C7984D2CD0F629008A18E2 /* CPDFDocument+PageEditManager.swift */; };
 		F3D395672CBD2C6D000C6729 /* KMNCustomAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D395662CBD2C6D000C6729 /* KMNCustomAlertView.swift */; };
 		F3D395682CBD2C6D000C6729 /* KMNCustomAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D395662CBD2C6D000C6729 /* KMNCustomAlertView.swift */; };
 		F3D395692CBD2C6D000C6729 /* KMNCustomAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D395662CBD2C6D000C6729 /* KMNCustomAlertView.swift */; };
+		F3D5D2AF2CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D5D2AD2CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift */; };
+		F3D5D2B02CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D5D2AD2CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift */; };
+		F3D5D2B12CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D5D2AD2CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift */; };
+		F3D5D2B32CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D5D2B22CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift */; };
+		F3D5D2B42CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D5D2B22CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift */; };
+		F3D5D2B52CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D5D2B22CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift */; };
 		F3DB85E52CCA1C4100D0AFDE /* ComponentGroupItem.nib in Resources */ = {isa = PBXBuildFile; fileRef = F3DB85E32CCA1C4100D0AFDE /* ComponentGroupItem.nib */; };
 		F3DB85E62CCA1C4100D0AFDE /* ComponentGroupItem.nib in Resources */ = {isa = PBXBuildFile; fileRef = F3DB85E32CCA1C4100D0AFDE /* ComponentGroupItem.nib */; };
 		F3DB85EC2CCA209600D0AFDE /* KMNBaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3DB85E92CCA209600D0AFDE /* KMNBaseViewController.swift */; };
@@ -6145,7 +6151,6 @@
 		9F1F82E12934D5240092C4B4 /* KMHomeExtractActionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMHomeExtractActionViewController.swift; sourceTree = "<group>"; };
 		9F1F82E22934D5240092C4B4 /* KMHomeExtractActionViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMHomeExtractActionViewController.xib; sourceTree = "<group>"; };
 		9F1F82E92935D02E0092C4B4 /* KMComboBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMComboBox.swift; sourceTree = "<group>"; };
-		9F1F82ED293609F50092C4B4 /* CPDFDocument+PageEditManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CPDFDocument+PageEditManager.swift"; sourceTree = "<group>"; };
 		9F1F82F129373D6E0092C4B4 /* String+KMExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+KMExtensions.swift"; sourceTree = "<group>"; };
 		9F1FE3DD293EE51F00E952CA /* KMMainDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMMainDocument.swift; sourceTree = "<group>"; };
 		9F1FE3F3293F4F0F00E952CA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -8215,8 +8220,11 @@
 		F3A9DC7D294309D80074E5D2 /* CPDFListEditAnnotationViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CPDFListEditAnnotationViewController.xib; sourceTree = "<group>"; };
 		F3B7DF992948565000333201 /* CPDFListHoverAnnotationViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CPDFListHoverAnnotationViewController.xib; sourceTree = "<group>"; };
 		F3B7DFA32949C8E300333201 /* CPDFListView.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = CPDFListView.xcassets; sourceTree = "<group>"; };
+		F3C7984D2CD0F629008A18E2 /* CPDFDocument+PageEditManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CPDFDocument+PageEditManager.swift"; sourceTree = "<group>"; };
 		F3D395662CBD2C6D000C6729 /* KMNCustomAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMNCustomAlertView.swift; sourceTree = "<group>"; };
 		F3D547B129559E1D00AA3953 /* ComPDFUIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComPDFUIKit.h; sourceTree = "<group>"; };
+		F3D5D2AD2CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "KMNThumbnailBaseViewController+Action.swift"; sourceTree = "<group>"; };
+		F3D5D2B22CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMNThumbnailCollectionView.swift; sourceTree = "<group>"; };
 		F3DB85E32CCA1C4100D0AFDE /* ComponentGroupItem.nib */ = {isa = PBXFileReference; lastKnownFileType = file; path = ComponentGroupItem.nib; sourceTree = "<group>"; };
 		F3DB85E92CCA209600D0AFDE /* KMNBaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KMNBaseViewController.swift; sourceTree = "<group>"; };
 		F3DB85EB2CCA209600D0AFDE /* KMNBaseWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KMNBaseWindowController.swift; sourceTree = "<group>"; };
@@ -9458,7 +9466,6 @@
 			children = (
 				9FAAA33D290FECA70046FFCE /* NSImage+QuickLook.swift */,
 				9F8DDF2529237910006CDC73 /* Array+KMExtensions.swift */,
-				9F1F82ED293609F50092C4B4 /* CPDFDocument+PageEditManager.swift */,
 				9F1F82F129373D6E0092C4B4 /* String+KMExtensions.swift */,
 				9F0CB4C3298625F400007028 /* NSColor+KMExtensions.swift */,
 				9FBC48BE299E23B100CA39D7 /* NSViewController+DesignToken.swift */,
@@ -15300,6 +15307,7 @@
 		F39603E42CC62E55003C6F71 /* KMNPDFPageEdit */ = {
 			isa = PBXGroup;
 			children = (
+				F3C7984D2CD0F629008A18E2 /* CPDFDocument+PageEditManager.swift */,
 				F3DB86022CCA691A00D0AFDE /* KMNPDFExtract */,
 				F3DB86052CCA691B00D0AFDE /* KMNPDFSplit */,
 				F337CC422CC7EDD000D46AF4 /* KMNPDFInsert */,
@@ -15312,8 +15320,10 @@
 		F39603EA2CC64374003C6F71 /* KMNThumbnailView */ = {
 			isa = PBXGroup;
 			children = (
+				F3D5D2B22CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift */,
 				F337CC1A2CC6456D00D46AF4 /* KMNThumbnailBaseViewController.swift */,
 				F337CC1B2CC6456D00D46AF4 /* KMNThumbnailBaseViewController.xib */,
+				F3D5D2AD2CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift */,
 				F337CC352CC6686100D46AF4 /* KMNThumbnailCollectionViewItem.swift */,
 				F337CC362CC6686100D46AF4 /* KMNThumbnailCollectionViewItem.xib */,
 				F337CC2E2CC64BD600D46AF4 /* KMNPageEditViewController.swift */,
@@ -17901,6 +17911,7 @@
 				89E4E7352964148E002DBA6F /* KMAnnotationPropertiesViewController.m in Sources */,
 				9F221ED729A9EC0900978A59 /* KMFillSignTextPanel.swift in Sources */,
 				BBF8A4032AE8E10100788BAC /* KMBatchConvertParameter.swift in Sources */,
+				F3D5D2B32CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift in Sources */,
 				BB1413682C69E6CA00BB8E35 /* KMURLConfigManager.swift in Sources */,
 				9FA607D928F8227500B46586 /* KMBox.swift in Sources */,
 				BBE9D0922AF0A85C002E83CE /* KMBatchOperation.swift in Sources */,
@@ -18441,7 +18452,6 @@
 				AD1D48212AFB6BBA007AC1F0 /* KMMergeView.swift in Sources */,
 				BBC3482929559B22008D2CD1 /* KMBackgroundListCell.swift in Sources */,
 				BBB9B316299A5D6D004F3235 /* KMDropboxManager.m in Sources */,
-				9F1F82EE293609F60092C4B4 /* CPDFDocument+PageEditManager.swift in Sources */,
 				89D2D2E2294C452B00BFF5FE /* KMPDFThumbnailView.swift in Sources */,
 				BB10FAE52AFE039E00F18D65 /* KMPDFEditPageRangeWindowController.swift in Sources */,
 				BB9599C32B31647B0062D346 /* KMRedactPropertiesWindowController.swift in Sources */,
@@ -18607,6 +18617,7 @@
 				ADB5E5122A371131007110A8 /* KMSubscribeWaterMarkWindowController.swift in Sources */,
 				ADDF83B02B391A5D00A81A4E /* KMDSignatureManager.m in Sources */,
 				BBC4F9EA2AEB58290098A1A8 /* KMAlertWindowController.swift in Sources */,
+				F3C7984E2CD0F62A008A18E2 /* CPDFDocument+PageEditManager.swift in Sources */,
 				BB147011299DC0D100784A6A /* OIDError.m in Sources */,
 				BBA93D2D29BEBAA60044E0DD /* KMPreferenceEnum.swift in Sources */,
 				ADDDCE212B43A32A005B4AB5 /* AppSandboxFileAccessPersist.m in Sources */,
@@ -18714,6 +18725,7 @@
 				651A59832C8EA210005A35FB /* KMPurchaseEmbeddedWindowController.swift in Sources */,
 				AD055E812B88294F0035F824 /* SKBookmarkController.m in Sources */,
 				ADE86AD12B04BAEA00414DFA /* KMCompareFilesView.swift in Sources */,
+				F3D5D2AF2CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift in Sources */,
 				BB146FCF299DC0D100784A6A /* GTMMIMEDocument.m in Sources */,
 				9F1F82EA2935D02E0092C4B4 /* KMComboBox.swift in Sources */,
 				ADDEEA722AD3EFE200EF675D /* KMButton.swift in Sources */,
@@ -18862,6 +18874,7 @@
 				AD055E5D2B85C9A70035F824 /* KMSeparatorCell.swift in Sources */,
 				ADE86A9E2B031FDB00414DFA /* KMCompareWindowController.swift in Sources */,
 				BB99ACC3292DE22E0048AFD9 /* KMMergeViewController.swift in Sources */,
+				F3C7984F2CD0F62A008A18E2 /* CPDFDocument+PageEditManager.swift in Sources */,
 				BB072D572C057BD600779B45 /* KMToolbarConfigWindowController.swift in Sources */,
 				9F5752EA2B58FF73005DC303 /* KMAnnotationFromViewController.swift in Sources */,
 				9F8810962B56877C00F69815 /* KMAnnotationChoiceWidgetOptionsViewController.swift in Sources */,
@@ -18878,7 +18891,6 @@
 				ADE614AD29779C5200F62ED7 /* KMImageTitleButton.swift in Sources */,
 				9FF94F0A29A62B5000B1EF69 /* KMDesignSelect.swift in Sources */,
 				BB146FBE299DC0D100784A6A /* GTMGatherInputStream.m in Sources */,
-				9F1F82EF293609F60092C4B4 /* CPDFDocument+PageEditManager.swift in Sources */,
 				BB8F4583295B0F900037EA22 /* KMHeaderFooterMarginInfoView.swift in Sources */,
 				9FB220ED2B185B3100A5B208 /* KMButtomCell.swift in Sources */,
 				9F1FE51229407B4000E952CA /* KMFileSearchView.swift in Sources */,
@@ -19380,6 +19392,7 @@
 				ADBC2D12299CCD05006280C8 /* KMTextfieldButton.swift in Sources */,
 				BBEFD0252AFA065F003FABD8 /* KMBatchAddHeaderFooterOperation.swift in Sources */,
 				9F1FE49429406E4700E952CA /* common.m in Sources */,
+				F3D5D2B02CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift in Sources */,
 				ADDF83AE2B391A5D00A81A4E /* DSignatureConfig.swift in Sources */,
 				BB6347C52AF24F6300F5438E /* KMBatchoperateConvertCollectionViewItem.swift in Sources */,
 				652E953E2C6670CE0061FA40 /* KMFreehandAnnotationController.swift in Sources */,
@@ -19551,6 +19564,7 @@
 				BB1BFF5E2AE9F1FF003EB179 /* KMBatchOperateBaseWindowController.swift in Sources */,
 				BB135C2B29B6CD9A00FD5965 /* KMTools.swift in Sources */,
 				9F1FE4A629406E4700E952CA /* CTToolbarView.m in Sources */,
+				F3D5D2B42CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift in Sources */,
 				BB162E9C295073B50088E9D1 /* KMWatermarkManager.swift in Sources */,
 				BB1331552AD7A6A1008F6791 /* KMFileAttribute.swift in Sources */,
 				BBD1F79D296FF7A600343885 /* KMPageEditSplitSettingModel.swift in Sources */,
@@ -20258,6 +20272,7 @@
 				BBF98C362C0EE46200436CC7 /* KMToolbarCustomItemView.swift in Sources */,
 				BB853C8C2AF8BC7D009C20C1 /* KMBatchAddPasswordOperation.swift in Sources */,
 				BBB14A5D2978EBBE00936EDB /* KMRedactMutilPageFlagContentView.swift in Sources */,
+				F3C798502CD0F62A008A18E2 /* CPDFDocument+PageEditManager.swift in Sources */,
 				BBF19E9B2B0B3218007154C8 /* KMAnnotationStamp.swift in Sources */,
 				9FE0BBED2B0F242C00CD1CAC /* NSUserDefaults_KMExtension.swift in Sources */,
 				BBBB6CDC2AD15B900035AA66 /* CPDFFreeTextAnnotation+PDFListView.swift in Sources */,
@@ -20624,7 +20639,6 @@
 				AD9527DD2952EE700039D2BC /* KMPrintPage_C.swift in Sources */,
 				9FDD0FB9295D5230000C4DAD /* KMToolbarController.swift in Sources */,
 				ADE614AE29779C5200F62ED7 /* KMImageTitleButton.swift in Sources */,
-				9F1F82F0293609F60092C4B4 /* CPDFDocument+PageEditManager.swift in Sources */,
 				BB89722B294B08720045787C /* KMWatermarkAdjectiveTopBarItemModel.swift in Sources */,
 				BB14700A299DC0D100784A6A /* OIDRegistrationRequest.m in Sources */,
 				654A5A842C895DE6001FBD4B /* KMComparativeGradientView.swift in Sources */,
@@ -21227,6 +21241,7 @@
 				BB3A66AD2B078FB200575343 /* KMNoteTableViewCell.swift in Sources */,
 				BB1B0AC12B4FC6E900889528 /* KMGuideInfoWindowController.swift in Sources */,
 				BB853C932AF8DCBF009C20C1 /* KMBatchOperateRemovePasswordViewController.swift in Sources */,
+				F3D5D2B12CCCD86400D4F1D5 /* KMNThumbnailBaseViewController+Action.swift in Sources */,
 				BB8B173E2907CDD9001C5EA5 /* NibLoadable.swift in Sources */,
 				9FCFEC862AD0EF6700EAD2CB /* KMCustomButtonPopMenuViewController.swift in Sources */,
 				BB7289E22B8838D8004B53B5 /* KMDataManager.swift in Sources */,
@@ -21412,6 +21427,7 @@
 				BBC3484C2958222C008D2CD1 /* KMBackgroundOutsideView.swift in Sources */,
 				AD0FA51429A9FA8600EDEB50 /* KMResetPasswordView.swift in Sources */,
 				9F0CB49129683DEE00007028 /* KMPropertiesPanelLineSubVC.swift in Sources */,
+				F3D5D2B52CCE31AC00D4F1D5 /* KMNThumbnailCollectionView.swift in Sources */,
 				9F8539C829430AC400DF644E /* KMToolbarRightView.swift in Sources */,
 				BBB2A99F2CB65C8E0066560B /* KMURLCreatePDFWindowController.swift in Sources */,
 				BBB9428D2BA2CB6A00542373 /* KMAdsInfo.swift in Sources */,