Browse Source

【UI替换】编辑工具 - 对比整体UI导入

lizhe 1 year ago
parent
commit
f81e3730de
38 changed files with 5060 additions and 23 deletions
  1. 376 0
      PDF Office/PDF Master.xcodeproj/project.pbxproj
  2. 246 0
      PDF Office/PDF Master/Class/PDFTools/Compare/KMCompareWindowController.swift
  3. 68 10
      PDF Office/PDF Master/Class/PDFTools/Compare/View/KMCompareView.swift
  4. 35 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/KMCompareContentWindowController.swift
  5. 43 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/KMCompareContentWindowController.xib
  6. 45 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/Model/KMCompareManager.swift
  7. 641 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareContentView.swift
  8. 381 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareContentView.xib
  9. 132 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareToolbar.swift
  10. 264 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareToolbar.xib
  11. 116 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextHeaderView.swift
  12. 18 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextHeaderView.xib
  13. 147 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextView.swift
  14. 190 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextView.xib
  15. 118 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextViewItem.swift
  16. 83 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextViewItem.xib
  17. 124 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbItem.swift
  18. 175 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbItem.xib
  19. 152 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbView.swift
  20. 98 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbView.xib
  21. 20 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/KMCompareContentSettingWindowController.swift
  22. 45 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/KMCompareContentSettingWindowController.xib
  23. 78 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/View/KMCompareContentSettingView.swift
  24. 120 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/View/KMCompareContentSettingView.xib
  25. 31 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/KMCompareCoveringWindowController.swift
  26. 43 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/KMCompareCoveringWindowController.xib
  27. 80 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/View/KMCompareCoveringView.swift
  28. 215 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/View/KMCompareCoveringView.xib
  29. 21 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/KMCompareCoveringSettingWindowController.swift
  30. 45 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/KMCompareCoveringSettingWindowController.xib
  31. 212 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/View/KMCompareCoveringSettingView.swift
  32. 354 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/View/KMCompareCoveringSettingView.xib
  33. 25 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/KMCompareSaveWindow.swift
  34. 43 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/KMCompareSaveWindow.xib
  35. 126 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/View/KMCompareSaveView.swift
  36. 15 0
      PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/View/KMCompareSaveView.xib
  37. 13 13
      PDF Office/PDF Master/Class/PDFTools/Crop/KMCropSettingWindowController.xib
  38. 122 0
      PDF Office/PDF Master/Class/PDFWindowController/ViewController/KMMainViewController+Action.swift

File diff suppressed because it is too large
+ 376 - 0
PDF Office/PDF Master.xcodeproj/project.pbxproj


+ 246 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/KMCompareWindowController.swift

@@ -7,9 +7,15 @@
 
 import Cocoa
 
+typealias KMCompareWindowControllerContentComplete = (_ controller: KMCompareWindowController, _ results: [CPDFCompareResults]  ,_ oldDocument: CPDFDocument, _ document: CPDFDocument) -> Void
+typealias KMCompareWindowControllerCoveringComplete = (_ controller: KMCompareWindowController, _ document: CPDFDocument) -> Void
+
 class KMCompareWindowController: KMBaseWindowController {
 
     @IBOutlet weak var compareView: KMCompareView!
+    
+    var pdfCompareContent: CPDFCompareContent?
+    
     var filePath: String = "" {
         didSet {
             if compareView != nil {
@@ -26,6 +32,9 @@ class KMCompareWindowController: KMBaseWindowController {
         }
     }
     
+    var contentComplete: KMCompareWindowControllerContentComplete?
+    var coveringComplete :KMCompareWindowControllerCoveringComplete?
+    
     override func windowDidLoad() {
         super.windowDidLoad()
 
@@ -35,5 +44,242 @@ class KMCompareWindowController: KMBaseWindowController {
         compareView.cancelAction = { [unowned self] view in
             cancelAction?(self)
         }
+        
+        compareView.doneAction = { [unowned self] view, config in
+            
+        }
+    }
+    
+    func compareAction(config: KMCompareFilesConfig) {
+
+        guard let pdfOldDocument = config.fileOldAttribute.pdfDocument, let pdfNewDocument = config.fileNewAttribute.pdfDocument else {
+            let alert = NSAlert()
+            alert.alertStyle = .critical
+            alert.messageText = NSLocalizedString("Please select two files to compare", comment: "")
+            alert.runModal()
+            return
+        }
+
+        let fileManager = FileManager.default
+        let fileOldPath = config.fileOldAttribute.pdfDocument?.documentURL.path
+        let fileNewPath = config.fileNewAttribute.pdfDocument?.documentURL.path
+
+        if !fileManager.fileExists(atPath: fileOldPath!) || !fileManager.fileExists(atPath: fileNewPath!){
+            let alert = NSAlert()
+            alert.alertStyle = .critical
+            alert.messageText = NSLocalizedString("The file has been deleted, please reselect a file.", comment: "")
+            alert.runModal()
+            return
+        }
+
+        if (config.fileNewAttribute.fetchSelectPages().count == 0) ||
+            (!config.fileNewAttribute.bAllPage && config.fileNewAttribute.pagesString.count < 1) {
+            let alert = NSAlert()
+            alert.alertStyle = .critical
+            alert.messageText = String(format: "%@ %@", (config.fileNewAttribute.pdfDocument?.documentURL.path.lastPathComponent.lastPathComponent)!, NSLocalizedString("Invalid page range. Please reselect the page range.", comment: ""))
+            alert.runModal()
+
+            config.fileNewAttribute.bAllPage = true
+            config.fileNewAttribute.pagesType = .all
+            
+            compareView.reloadData()
+            return
+        }
+
+        if (config.fileOldAttribute.fetchSelectPages().count == 0) || (!config.fileOldAttribute.bAllPage && config.fileOldAttribute.pagesString.count < 1) {
+            let alert = NSAlert()
+            alert.alertStyle = .critical
+            alert.messageText = String(format: "%@ %@", (config.fileOldAttribute.pdfDocument?.documentURL.path.lastPathComponent.lastPathComponent)!, NSLocalizedString("Invalid page range. Please reselect the page range.", comment: ""))
+            alert.runModal()
+
+            config.fileOldAttribute.bAllPage = true
+            config.fileOldAttribute.pagesType = .all
+
+            compareView.reloadData()
+            return
+        }
+
+        let filePath = config.fileOldAttribute.pdfDocument?.documentURL.path
+        let pdfDocument = CPDFDocument(url: URL(fileURLWithPath: filePath!))
+
+//        if pdfDocument!.isLocked && self.pdfOldDocument?.isLocked == true {
+//            DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
+//                let passwordWC = PasswordWindowController(windowNibName: "PasswordWindowController")
+//                passwordWC.fileURL = URL(fileURLWithPath: filePath)
+//                passwordWC.beginSheetModalForWindow(self.window) { password in
+//                    if let password = password {
+//                        pdfDocument.unlock(withPassword: password)
+//                        config.fileOldAttribute.pdfDocument = pdfDocument
+//                        config.fileOldAttribute.password = password
+//                        config.fileOldAttribute.bAllPage = true
+//                        config.fileOldAttribute.pagesType = PDFSeleectPageType_AllPages
+//                        self.pdfOldDocument = PDFDocument(url: URL(fileURLWithPath: filePath))
+//                        if self.pdfOldDocument?.isLocked == true {
+//                            self.pdfOldDocument?.unlock(withPassword: password)
+//                        }
+//                        self.oldPDFView.document = self.pdfOldDocument
+//                        self.oldPDFView.autoScales = true
+//                        self.oldPDFView.delegate = self
+//                        self.updateOldFileQKSelectedPathsWithPath(self.pdfOldDocument?.documentURL?.path ?? "")
+//                        self.reloadOldPDFData()
+//                    }
+//                }
+//            }
+//            return
+//        }
+
+        let filePath1 = config.fileNewAttribute.pdfDocument?.documentURL.path
+        let pdfDocument1 = CPDFDocument(url: URL(fileURLWithPath: filePath1!))
+
+//        if pdfDocument1.isLocked && self.pdfNewDocument?.isLocked == true {
+//            DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
+//                let passwordWC = PasswordWindowController(windowNibName: "PasswordWindowController")
+//                passwordWC.fileURL = URL(fileURLWithPath: filePath1)
+//                passwordWC.beginSheetModalForWindow(self.window) { password in
+//                    if let password = password {
+//                        pdfDocument.unlock(withPassword: password)
+//                        config.fileNewAttribute.pdfDocument = pdfDocument1
+//                        config.fileNewAttribute.password = password
+//                        config.fileNewAttribute.bAllPage = true
+//                        config.fileNewAttribute.pagesType = PDFSeleectPageType_AllPages
+//                        self.pdfNewDocument = PDFDocument(url: URL(fileURLWithPath: filePath1))
+//                        if self.pdfNewDocument?.isLocked == true {
+//                            self.pdfNewDocument?.unlock(withPassword: password)
+//                        }
+//                        self.pdfNewView.document = self.pdfNewDocument
+//                        self.pdfNewView.autoScales = true
+//                        self.pdfNewView.delegate = self
+//                        self.addFileContentView.isHidden = true
+//                        self.updateNewFileQKSelectedPathsWithPath(self.pdfNewDocument?.documentURL?.path ?? "")
+//                        self.reloadNewPDFData()
+//                    }
+//                }
+//            }
+//            return
+//        }
+
+        DispatchQueue.global().async {
+            let oldDoc = CPDFDocument(url: config.fileOldAttribute.pdfDocument?.documentURL)
+            if let password = config.fileOldAttribute.password {
+                oldDoc!.unlock(withPassword: password)
+            }
+            let doc = CPDFDocument(url: config.fileNewAttribute.pdfDocument?.documentURL)
+            if let password = config.fileNewAttribute.password {
+                doc!.unlock(withPassword: password)
+            }
+            
+//            if let compareLoadingWVC = self.compareLoadingWVC {
+//                compareLoadingWVC.maxPageCount = config.fileOldAttribute.pdfDocument.pageCount + config.fileNewAttribute.pdfDocument.pageCount
+//            }
+            
+//            if self._compareCancel {
+//                return
+//            }
+            
+            if self.compareView.fileType == .coverting {
+                let pdfCompareOverlay = CPDFCompareOverlay(oldDocument: oldDoc, oldPageRange: config.fileOldAttribute.pagesString, newDocument: doc, newPageRange: config.fileNewAttribute.pagesString)
+                
+                let oldStrokeColor = config.oldStrokeColor
+                pdfCompareOverlay?.setOldDocumentStroke(oldStrokeColor())
+                pdfCompareOverlay?.setOldDocumentStrokeOpacity(config.oldStrokeOpacity())
+                
+                let newStrokeColor = config.newStrokeColor
+                pdfCompareOverlay?.setNewDocumentStroke(newStrokeColor())
+                pdfCompareOverlay?.setNewDocumentStrokeOpacity(config.newStrokeOpacity())
+                pdfCompareOverlay?.setNewDocumentFillOpacity(config.newFillOpacity())
+                pdfCompareOverlay?.setOldDocumentFillOpacity(config.oldFillOpacity())
+                pdfCompareOverlay?.setNoFill(config.isNOFill())
+                pdfCompareOverlay?.setBlendMod(config.blendMod())
+
+                if ((pdfCompareOverlay?.compare()) != nil) {
+                    let document: CPDFDocument = (pdfCompareOverlay?.comparisonDocument()!)!
+                    if document == nil {
+                        DispatchQueue.main.async {
+                            self.coveringComplete?(self, document)
+                        }
+                        debugPrint("合并成功")
+                    } else {
+                        DispatchQueue.main.async {
+                            let alert = NSAlert()
+                            alert.alertStyle = .critical
+                            alert.messageText = NSLocalizedString("Failure", comment: "")
+                            alert.runModal()
+                        }
+                    }
+                }
+            } else {
+                var results = [CPDFCompareResults]()
+                var pdfCompareContent: CPDFCompareContent? = nil
+                
+//                if let _pdfCompareContent = self._pdfCompareContent {
+//                    pdfCompareContent = _pdfCompareContent
+//                }
+//                
+//                if self._compareCancel {
+//                    return
+//                }
+                
+                pdfCompareContent = CPDFCompareContent(oldDocument: oldDoc, newDocument: doc)
+                
+                pdfCompareContent?.setDelete(config.deleteColor())
+                pdfCompareContent?.setReplace(config.replaceColor())
+                pdfCompareContent?.setInsert(config.insertColor())
+                pdfCompareContent?.setDeleteOpacity(config.deleteOpacity())
+                pdfCompareContent?.setReplaceOpacity(config.replaceOpacity())
+                pdfCompareContent?.setInsertOpacity(config.insertOpacity())
+                
+                let maxIndex = max(config.fileOldAttribute.fetchSelectPages().count, config.fileNewAttribute.fetchSelectPages().count)
+                
+                var compareType: CPDFCompareType = .all
+                if config.isCompareText() && !config.isCompareImage() {
+                    compareType = .text
+                } else if !config.isCompareText() && config.isCompareImage() {
+                    compareType = .image
+                }
+                
+//                if self._compareCancel {
+//                    return
+//                }
+                
+                for i in 0..<maxIndex {
+                    let oldPageIndex: Int
+                    if i >= config.fileOldAttribute.fetchSelectPages().count {
+                        oldPageIndex = Int(oldDoc!.pageCount) + i
+                    } else {
+                        oldPageIndex = Int(truncating: config.fileOldAttribute.fetchSelectPages()[i]) - 1
+                    }
+                    
+                    let newPageIndex: Int
+                    if i >= config.fileNewAttribute.fetchSelectPages().count {
+                        newPageIndex = Int(doc!.pageCount) + i
+                    } else {
+                        newPageIndex = Int(truncating: config.fileNewAttribute.fetchSelectPages()[i]) - 1
+                    }
+
+                    if let compareResults = pdfCompareContent?.compareOldPageIndex(oldPageIndex, newPageIndex: newPageIndex, type: compareType, isDrawHighlight: true) {
+                        results.append(compareResults)
+                    }
+                    
+//                    DispatchQueue.main.async {
+//                        if let compareLoadingWVC = self.compareLoadingWVC {
+//                            compareLoadingWVC.progress = CGFloat(i) / CGFloat(maxIndex)
+//                        }
+//                    }
+                }
+                
+                DispatchQueue.main.async {
+                    self.contentComplete?(self,results, oldDoc!, doc!)
+                    if results.count > 0 {
+                        // Handle success case
+                    } else {
+                        let alert = NSAlert()
+                        alert.alertStyle = .critical
+                        alert.messageText = NSLocalizedString("There is no difference between the two documents.", comment: "")
+                        alert.runModal()
+                    }
+                }
+            }
+        }
+
     }
 }

+ 68 - 10
PDF Office/PDF Master/Class/PDFTools/Compare/View/KMCompareView.swift

@@ -8,6 +8,7 @@
 import Cocoa
 
 typealias KMCompareViewCancelAction = (_ view: KMCompareView) -> Void
+typealias KMCompareViewDoneAction = (_ view: KMCompareView, _ config: KMCompareFilesConfig) -> Void
 
 enum KMCompareFilesType {
     case content
@@ -63,6 +64,9 @@ class KMCompareView: KMBaseXibView {
     @IBOutlet weak var compareSettingsBtn: NSButton!
     @IBOutlet weak var settingBtnTopLayout: NSLayoutConstraint!
     
+    var contentSettingWindowController: KMCompareContentSettingWindowController?
+    var coveringSettingWindowController: KMCompareCoveringSettingWindowController?
+    
     var pdfCompareContent: CPDFCompareContent?
     
     var filePath: String? {
@@ -85,6 +89,7 @@ class KMCompareView: KMBaseXibView {
     }
     
     var cancelAction: KMCompareViewCancelAction?
+    var doneAction: KMCompareViewDoneAction?
     
     convenience init(pdfDocument: PDFDocument) {
         self.init()
@@ -401,8 +406,8 @@ extension KMCompareView {
         var currentPageLabel = NSTextField()
         var totalPageLabel = NSTextField()
         
-        addFileContentView.isHidden = false
         if isNew {
+            addFileContentView.isHidden = false
             guard let document = KMCompareFilesConfig.defaultConfig.fileNewAttribute.pdfDocument else { return }
             pdfView = pdfNewView
             pageDocument = pdfView.document!
@@ -412,7 +417,7 @@ extension KMCompareView {
         } else {
             guard let document = KMCompareFilesConfig.defaultConfig.fileOldAttribute.pdfDocument else { return }
             pdfView = oldPDFView
-            pageDocument = pdfView.document!
+            pageDocument = pdfView.document ?? document as! PDFDocument
             currentPageLabel = currentOldPageLabel
             totalPageLabel = totalPaOldgeLabel
         }
@@ -506,7 +511,42 @@ extension KMCompareView {
         }
     }
     
-    
+    func updatePageRange(view: NSComboBox, isNew: Bool = false) {
+        let config = KMCompareFilesConfig.defaultConfig
+        let index = pageRangeOldComboBox.indexOfSelectedItem
+        
+        var file = config.fileOldAttribute
+        if isNew {
+            file = config.fileNewAttribute
+        }
+        switch index {
+        case 0:
+            file.bAllPage = true
+            file.pagesType = .all
+            view.delegate = nil
+            view.isEditable = false
+        case 1:
+            file.bAllPage = false
+            file.pagesType = .odd
+            view.delegate = nil
+            view.isEditable = false
+        case 2:
+            file.bAllPage = false
+            file.pagesType = .even
+            view.delegate = nil
+            view.isEditable = false
+        case 3:
+            file.bAllPage = false
+            file.pagesType = .all
+            view.delegate = self
+            view.stringValue = ""
+            view.isEditable = true
+            view.isSelectable = true
+            self.window?.makeFirstResponder(view)
+        default:
+            break
+        }
+    }
 }
 
 extension KMCompareView {
@@ -517,7 +557,9 @@ extension KMCompareView {
     }
     
     @IBAction func convertButtonAction(_ sender: Any) {
+        guard let callBack = doneAction else { return }
         
+        callBack(self, KMCompareFilesConfig.defaultConfig)
     }
     
     @IBAction func oldFilesSelectBoxAction(_ sender: Any) {
@@ -565,23 +607,39 @@ extension KMCompareView {
     }
     
     @IBAction func oldPageRangeBoxAction(_ sender: Any) {
-        
+        self.updatePageRange(view: self.pageRangeOldComboBox)
     }
     
     @IBAction func newPageRangeBoxAction(_ sender: Any) {
-        
+        self.updatePageRange(view: self.pageRangeOldComboBox, isNew: true)
     }
     
-    @IBAction func compareTextButtonAction(_ sender: Any) {
-        
+    @IBAction func compareTextButtonAction(_ sender: NSButton) {
+        let isCompareText = sender.state == .on ?true:false
+        KMCompareFilesConfig.defaultConfig.setIsCompareText(isCompareText)
     }
     
-    @IBAction func compareImageButtonAction(_ sender: Any) {
-        
+    @IBAction func compareImageButtonAction(_ sender: NSButton) {
+        let isCompareImage = sender.state == .on ?true:false
+        KMCompareFilesConfig.defaultConfig.setIsCompareImage(isCompareImage)
     }
     
     @IBAction func settingButtonAction(_ sender: Any) {
-        
+        if fileType == .content {
+            if contentSettingWindowController == nil {
+                let controller = KMCompareContentSettingWindowController(windowNibName: "KMCompareContentSettingWindowController")
+                contentSettingWindowController = controller
+            }
+            NSWindow.currentWindow().addChildWindow(contentSettingWindowController!.window!, ordered: .above)
+            contentSettingWindowController!.window?.center()
+        } else {
+            if coveringSettingWindowController == nil {
+                let controller = KMCompareCoveringSettingWindowController(windowNibName: "KMCompareCoveringSettingWindowController")
+                coveringSettingWindowController = controller
+            }
+            NSWindow.currentWindow().addChildWindow(coveringSettingWindowController!.window!, ordered: .above)
+            coveringSettingWindowController!.window?.center()
+        }
     }
     
     @objc func segmentedControlClicked(sender: NSSegmentedControl) {

+ 35 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/KMCompareContentWindowController.swift

@@ -0,0 +1,35 @@
+//
+//  KMCompareContentWindowController.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareContentWindowController: NSWindowController {
+
+    @IBOutlet weak var contentView: KMCompareContentView!
+    
+    var results: [CPDFCompareResults] = []
+    var pdfDocument: CPDFDocument?
+    var pdfOldDocumnet: CPDFDocument?
+    var hideCloseInfo: Bool = false
+    
+    var saveHandle: ((KMCompareContentWindowController) -> Void)?
+    var closeHandle: ((KMCompareContentWindowController) -> Void)?
+    
+    convenience init(document: CPDFDocument, oldDocument: CPDFDocument, results: [CPDFCompareResults]) {
+        self.init(windowNibName: "KMCompareContentWindowController")
+        self.results = results
+        self.pdfOldDocumnet = oldDocument
+        self.pdfDocument = document
+    }
+    
+    override func windowDidLoad() {
+        super.windowDidLoad()
+
+        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
+    }
+    
+}

+ 43 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/KMCompareContentWindowController.xib

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareContentWindowController" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="contentView" destination="SOI-lJ-31P" id="pSa-PN-rjU"/>
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+            <rect key="contentRect" x="196" y="240" width="632" height="384"/>
+            <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="632" height="384"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="SOI-lJ-31P" customClass="KMCompareContentView" customModule="PDF_Master" customModuleProvider="target">
+                        <rect key="frame" x="0.0" y="0.0" width="632" height="384"/>
+                    </customView>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="SOI-lJ-31P" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" id="jQo-RW-h5G"/>
+                    <constraint firstAttribute="bottom" secondItem="SOI-lJ-31P" secondAttribute="bottom" id="nxR-VW-ctp"/>
+                    <constraint firstAttribute="trailing" secondItem="SOI-lJ-31P" secondAttribute="trailing" id="sRH-Py-ysh"/>
+                    <constraint firstItem="SOI-lJ-31P" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" id="xHg-3u-8RD"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
+            </connections>
+            <point key="canvasLocation" x="215" y="163"/>
+        </window>
+    </objects>
+</document>

+ 45 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/Model/KMCompareManager.swift

@@ -0,0 +1,45 @@
+//
+//  KMCompareManager.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareManager: NSObject {
+    var showToolbar: Bool = false
+    var compareThumbType: Bool = false
+    var maxPageCount: UInt = 0
+    var isSelectedOldPDF: Bool = false
+    var pdfSelectedIndex: UInt = 0
+    var compareResultModels: [KMCompareResultModel] = []
+    var isSyncScroll: Bool = false
+    var isThumbItemClicked: Bool = false
+    
+    static var manager: KMCompareManager = KMCompareManager()
+}
+
+class KMCompareResultModel: NSObject {
+    
+    var isExpand: Bool = false
+    var compareResults: [Any] = [] // Replace 'Any' with the actual type of compareResults
+    var results: CPDFCompareResults = CPDFCompareResults() // Replace 'CPDFCompareResults' with the actual type
+    var resultCounts: UInt = 0
+}
+
+extension CPDFCompareResult {
+    
+    var isTextResult: Bool {
+        get {
+            if let num = objc_getAssociatedObject(self, "SKPDFViewAutoFlowTimerKey") as? NSNumber {
+                return num.boolValue
+            }
+            return false
+        }
+        set {
+            let value = NSNumber(value: newValue)
+            objc_setAssociatedObject(self, "SKPDFViewAutoFlowTimerKey", value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+}

+ 641 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareContentView.swift

@@ -0,0 +1,641 @@
+//
+//  KMCompareContentView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareContentView: KMBaseXibView, CPDFViewDelegate, KMCompareToolbarDelegate, KMCompareThumbViewDelegate, KMCompareTextViewDelegate, NSSplitViewDelegate {
+    
+    @IBOutlet weak var contendView: NSView!
+    @IBOutlet weak var topToolbarBox: NSBox!
+    
+    @IBOutlet weak var deleteBGView: NSView!
+    @IBOutlet weak var deleteColorView: NSView!
+    @IBOutlet weak var deleteLbl: NSTextField!
+    
+    @IBOutlet weak var replaceBGView: NSView!
+    @IBOutlet weak var replaceColorView: NSView!
+    @IBOutlet weak var replaceLbl: NSTextField!
+    
+    @IBOutlet weak var insertBGView: NSView!
+    @IBOutlet weak var insertColorView: NSView!
+    @IBOutlet weak var insertLbl: NSTextField!
+    
+    @IBOutlet weak var syncScrollBtn: NSButton!
+    
+    @IBOutlet weak var toolbarShowBtn: NSButton!
+    @IBOutlet weak var toolbarRightConst: NSLayoutConstraint!
+    
+    @IBOutlet weak var saveBtn: NSButton!
+    @IBOutlet weak var saveBoxWidthConst: NSLayoutConstraint!
+    
+    @IBOutlet weak var closeBox: NSBox!
+    @IBOutlet weak var closeBtn: NSButton!
+    
+    @IBOutlet weak var compareInfoView: NSView!
+    
+    @IBOutlet weak var compareThumbBox: NSBox!
+    @IBOutlet weak var compareThumbBtn: NSButton!
+    @IBOutlet weak var compareThumbImg: NSImageView!
+    
+    @IBOutlet weak var compareFileBox: NSBox!
+    @IBOutlet weak var compareFileBtn: NSButton!
+    @IBOutlet weak var compareFileImg: NSImageView!
+    
+    @IBOutlet weak var compareDetailView: NSView!
+    
+    @IBOutlet weak var splitView: NSSplitView!
+    @IBOutlet weak var splitAView: NSView!
+    @IBOutlet weak var splitBView: NSView!
+    
+    @IBOutlet weak var pdfOldView: CPDFView!
+    @IBOutlet weak var pdfNewView: CPDFView!
+    
+    var oldDocument: CPDFDocument = CPDFDocument()
+    var document: CPDFDocument = CPDFDocument()
+    
+    var compareToolbar: KMCompareToolbar = KMCompareToolbar()
+    var nFileCompareToolbar: KMCompareToolbar = KMCompareToolbar()
+    
+    var thumbController: KMCompareThumbView = KMCompareThumbView()
+    var textController: KMCompareTextView = KMCompareTextView()
+    
+    var compareResults: [CPDFCompareResults] = []
+    
+    var compareManager: KMCompareManager = KMCompareManager()
+    
+    var pdfoldViewSPoint: CGPoint = CGPoint.zero
+    var pdfnewViewSPoint: CGPoint = CGPoint.zero
+    
+    var isOldFileFirst: Bool = false
+    var isNewFileFirst: Bool = false
+    var isToolbarAction: Bool = false
+    
+    var oldToNewPDFScale: CGFloat = 0.0
+    
+    var saveHandle: ((KMCompareContentView) -> Void)?
+    var closeHandle: ((KMCompareContentView) -> Void)?
+
+    convenience init(results: [CPDFCompareResults], oldDocument: CPDFDocument, document: CPDFDocument) {
+        self.init()
+        
+        self.oldDocument = oldDocument
+        self.document = document
+        self.compareResults = results
+        
+        self.compareManager.showToolbar = true
+        self.compareManager.isSyncScroll = true
+        
+        self.compareManager.compareResultModels.removeAll()
+        
+        for result in results {
+            let model = KMCompareResultModel()
+            model.isExpand = true
+            model.results = result
+            model.resultCounts = UInt((result as AnyObject).deleteCount() + (result as AnyObject).insertCount() + (result as AnyObject).replaceCount())
+            
+            for compareResult in (result as AnyObject).textResults() {
+                    compareResult.isTextResult = true
+                model.compareResults.append(compareResult)
+            }
+            
+            for compareResult in (result as AnyObject).imageResults() {
+                    compareResult.isTextResult = false
+                model.compareResults.append(compareResult)
+            }
+            
+            if model.compareResults.count > 0 {
+                self.compareManager.compareResultModels.append(model)
+            }
+        }
+    }
+    
+    override func setup() {
+        self.wantsLayer = true
+        self.layer?.backgroundColor = NSColor.clear.cgColor
+        
+        
+        [deleteColorView, replaceColorView, insertColorView].forEach {
+            $0.wantsLayer = true
+            $0.layer?.cornerRadius = 4
+            $0.layer?.masksToBounds = true
+        }
+        
+
+        let size = saveBtn.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: saveBtn.frame.size.height))
+        saveBoxWidthConst.constant = max(74, size.width + 10)
+        saveBtn.contentTintColor = NSColor.white
+        
+        closeBtn.contentTintColor = NSColor.white
+        
+        compareDetailView.wantsLayer = true
+        compareDetailView.layer?.backgroundColor = NSColor.clear.cgColor
+        
+        compareToolbar.frame = CGRectMake(splitAView.frame.width/2 - 160, 20, 320, 40)
+        compareToolbar.autoresizingMask = [.minXMargin, .maxXMargin, .maxYMargin]
+        compareToolbar.delegate = self
+        compareToolbar.shadow = NSShadow()
+        compareToolbar.layer?.shadowColor = NSColor.black.withAlphaComponent(0.15).cgColor
+        compareToolbar.layer?.cornerRadius = 4.0
+        compareToolbar.layer?.shadowRadius = 4.0
+        
+        compareToolbar.filePath = oldDocument.documentURL?.path ?? ""
+        compareToolbar.totalPage = Int(oldDocument.pageCount)
+        compareToolbar.currentPage = pdfOldView.currentPageIndex + 1
+        compareToolbar.refreshButtonState()
+        
+        splitAView.addSubview(compareToolbar)
+        
+        nFileCompareToolbar = KMCompareToolbar()
+        nFileCompareToolbar.frame = CGRect(x: splitBView.frame.width/2 - 160, y: 20, width: 320, height: 40)
+        nFileCompareToolbar.autoresizingMask = [.minXMargin, .maxXMargin, .maxYMargin]
+        nFileCompareToolbar.delegate = self
+        nFileCompareToolbar.shadow = NSShadow()
+        nFileCompareToolbar.layer?.shadowColor = NSColor.black.withAlphaComponent(0.15).cgColor
+        nFileCompareToolbar.layer?.cornerRadius = 4.0
+        nFileCompareToolbar.layer?.shadowRadius = 4.0
+        splitBView.addSubview(nFileCompareToolbar)
+        
+        nFileCompareToolbar.filePath = document.documentURL?.path ?? ""
+        nFileCompareToolbar.totalPage = Int(document.pageCount)
+        nFileCompareToolbar.currentPage = pdfNewView.currentPageIndex + 1
+        nFileCompareToolbar.refreshButtonState()
+        
+        splitView.delegate = self
+        
+        refreshToolbarInfoState()
+        
+        pdfOldView.document = oldDocument
+        pdfOldView.scaleFactor = 1
+        pdfOldView.delegate = self
+        
+        pdfNewView.document = document
+        pdfNewView.scaleFactor = 1
+        pdfNewView.delegate = self
+        
+
+        
+        compareManager.maxPageCount = max(oldDocument.pageCount, document.pageCount)
+        
+        textController.compareManager = compareManager
+        textController.frame = compareDetailView.bounds
+        textController.autoresizingMask = [.width, .height]
+        textController.delegate = self
+        compareDetailView.addSubview(textController)
+        textController.reloadData()
+        
+        refreshCompareColorView()
+        refreshCompareTypeInfo()
+    }
+    
+    override func addNotification() {
+        NotificationCenter.default.addObserver(self,
+                                               selector: #selector(oldPDFViewboundsDidChangeNotification(_:)),
+                                               name: NSView.boundsDidChangeNotification,
+                                               object: pdfOldView.documentView().contentView)
+        
+        NotificationCenter.default.addObserver(self,
+                                               selector: #selector(newPDFViewboundsDidChangeNotification(_:)),
+                                               name: NSView.boundsDidChangeNotification,
+                                               object: pdfNewView.documentView().contentView)
+    }
+    
+
+    override func updateLanguage() {
+        deleteLbl.stringValue = NSLocalizedString("Delete", comment: "")
+        replaceLbl.stringValue = NSLocalizedString("Replace", comment: "")
+        insertLbl.stringValue = NSLocalizedString("Insert", comment: "")
+        
+        toolbarShowBtn.title = NSLocalizedString("Bottom Toolbar", comment: "")
+        syncScrollBtn.title = NSLocalizedString("Scroll Sync", comment: "")
+        
+        saveBtn.title = NSLocalizedString("Save", comment: "")
+        
+        closeBtn.title = NSLocalizedString("Close", comment: "")
+    }
+    
+    override func reloadData() {
+        splitView.setPosition(splitView.frame.width / 2, ofDividerAt: 0)
+        
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
+            self.pdfOldView.go(toPageIndex: 0, animated: true)
+            self.pdfNewView.go(toPageIndex: 0, animated: true)
+        }
+        
+        oldToNewPDFScale = pdfOldView.scaleFactor / pdfNewView.scaleFactor
+    }
+    
+    func showImageController() {
+        thumbController = KMCompareThumbView()
+        thumbController.compareManager = compareManager
+        thumbController.frame = compareDetailView.bounds
+        thumbController.delegate = self
+        thumbController.autoresizingMask = [.width, .height]
+        thumbController.oldDocument = oldDocument
+        thumbController.nDocument = document
+        compareDetailView.addSubview(thumbController)
+        
+        refreshCompareColorView()
+        refreshCompareTypeInfo()
+    }
+
+    // MARK: - Setter
+    var hideCloseInfo: Bool = false {
+        didSet {
+            if hideCloseInfo {
+                closeBox.isHidden = true
+                toolbarRightConst.constant = 16
+            } else {
+                closeBox.isHidden = false
+                toolbarRightConst.constant = 106
+            }
+        }
+    }
+
+    func refreshCompareColorView() {
+        let config = KMCompareFilesConfig.defaultConfig
+        
+        var insertColor = config.insertColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        insertColor = insertColor?.withAlphaComponent(config.insertOpacity())
+        
+
+        var deleteColor = config.deleteColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        deleteColor = deleteColor?.withAlphaComponent(config.deleteOpacity())
+        
+        var replaceColor = config.replaceColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        replaceColor = replaceColor?.withAlphaComponent(config.replaceOpacity())
+        
+        
+        deleteColorView.layer?.backgroundColor = deleteColor?.cgColor
+        replaceColorView.layer?.backgroundColor = replaceColor?.cgColor
+        insertColorView.layer?.backgroundColor = insertColor?.cgColor
+    }
+
+    func refreshToolbarInfoState() {
+        if compareManager.showToolbar {
+            compareToolbar.isHidden = false
+            nFileCompareToolbar.isHidden = false
+            toolbarShowBtn.state = .on
+        } else {
+            compareToolbar.isHidden = true
+            nFileCompareToolbar.isHidden = true
+            toolbarShowBtn.state = .off
+        }
+        
+        syncScrollBtn.state = compareManager.isSyncScroll ? .on : .off
+    }
+
+    func refreshCompareTypeInfo() {
+        if compareManager.compareThumbType {
+            showImageController()
+            compareThumbBox.fillColor = KMAppearance.Interactive.a0Color()
+            compareFileBox.fillColor = KMAppearance.Layout.l1Color()
+            thumbController.isHidden = false
+            textController.isHidden = true
+            compareThumbImg.image = NSImage(named: "ic_sidetabbar_thumbnail_white_nor")
+            compareFileImg.image = NSImage(named: "ic_compare_result_text_dark")
+        } else {
+            compareFileBox.fillColor = KMAppearance.Interactive.a0Color()
+            compareThumbBox.fillColor = KMAppearance.Layout.l1Color()
+            thumbController.isHidden = true
+            textController.isHidden = false
+            textController.reloadData()
+            compareThumbImg.image = NSImage(named: "ic_sidetabbar_thumbnail_black_nor")
+            compareFileImg.image = NSImage(named: "ic_compare_result_text")
+        }
+    }
+    
+    // MARK: - IBAction
+
+    @IBAction func changeCompareType(_ sender: NSButton) {
+        if sender == compareFileBtn {
+            compareManager.compareThumbType = false
+        } else if sender == compareThumbBtn {
+            compareManager.compareThumbType = true
+        }
+        refreshCompareTypeInfo()
+    }
+
+    @IBAction func showToolbarAction(_ sender: NSButton) {
+        if toolbarShowBtn.state == .on {
+            compareManager.showToolbar = true
+        } else {
+            compareManager.showToolbar = false
+        }
+        refreshToolbarInfoState()
+    }
+
+    @IBAction func syncScrollBtnAction(_ sender: NSButton) {
+        if syncScrollBtn.state == .on {
+            compareManager.isSyncScroll = true
+        } else {
+            compareManager.isSyncScroll = false
+        }
+        refreshToolbarInfoState()
+    }
+
+    @IBAction func saveButtonAction(_ sender: NSButton) {
+        saveHandle?(self)
+    }
+
+    @IBAction func closeBtnAction(_ sender: NSButton) {
+        closeHandle?(self)
+    }
+
+    // MARK: - CPDFViewDelegate
+
+    func pdfViewCurrentPageDidChanged(_ pdfView: CPDFView) {
+        if compareManager.isSyncScroll {
+            if isOldFileFirst {
+                let index = pdfOldView.currentPageIndex
+                compareManager.isSelectedOldPDF = true
+                compareManager.pdfSelectedIndex = UInt(index)
+            } else if isNewFileFirst {
+                let index = pdfNewView.currentPageIndex
+                compareManager.isSelectedOldPDF = false
+                compareManager.pdfSelectedIndex = UInt(index)
+            }
+
+            compareToolbar.currentPage = pdfOldView.currentPageIndex + 1
+            nFileCompareToolbar.currentPage = pdfNewView.currentPageIndex + 1
+            compareToolbar.refreshButtonState()
+            nFileCompareToolbar.refreshButtonState()
+
+            if compareManager.compareThumbType {
+                NotificationCenter.default.post(name: Notification.Name("CPDFThumbSelectChangedNoti"), object: nil)
+                thumbController.pdfSelectionChanged()
+            }
+        } else {
+            if pdfView == pdfOldView {
+                let index = pdfOldView.currentPageIndex
+                compareManager.isSelectedOldPDF = true
+                compareManager.pdfSelectedIndex = UInt(index)
+            } else if pdfView == pdfNewView {
+                let index = pdfNewView.currentPageIndex
+                compareManager.isSelectedOldPDF = false
+                compareManager.pdfSelectedIndex = UInt(index)
+            }
+            compareToolbar.currentPage = pdfOldView.currentPageIndex + 1
+            nFileCompareToolbar.currentPage = pdfNewView.currentPageIndex + 1
+            compareToolbar.refreshButtonState()
+            nFileCompareToolbar.refreshButtonState()
+
+            if compareManager.compareThumbType {
+                NotificationCenter.default.post(name: Notification.Name("CPDFThumbSelectChangedNoti"), object: nil)
+                thumbController.pdfSelectionChanged()
+            }
+        }
+    }
+
+    func pdfViewScaleDidChanged(_ pdfView: CPDFView) {
+        oldToNewPDFScale = pdfOldView.scaleFactor / pdfNewView.scaleFactor
+    }
+
+    // MARK: - CPDFCompareToolbarDelegate
+
+    func compareToolbar(_ toolbar: KMCompareToolbar, didActionEnable action: CPDFCompareToolbarAction) -> Bool {
+        switch action {
+        case .Increase:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                return pdfOldView.canZoomIn
+            } else if toolbar.filePath == document.documentURL.path {
+                return pdfNewView.canZoomIn
+            }
+        case .Reduce:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                return pdfOldView.canZoomOut
+            } else if toolbar.filePath == document.documentURL.path {
+                return pdfNewView.canZoomOut
+            }
+        case .FirstPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                return pdfOldView.currentPageIndex > 0
+            } else if toolbar.filePath == document.documentURL.path {
+                return pdfNewView.currentPageIndex > 0
+            }
+        case .LastPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                return pdfOldView.currentPageIndex < pdfOldView.document.pageCount - 1
+            } else if toolbar.filePath == document.documentURL.path {
+                return pdfNewView.currentPageIndex < pdfNewView.document.pageCount - 1
+            }
+        case .PreviousPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                return pdfOldView.currentPageIndex > 0
+            } else if toolbar.filePath == document.documentURL.path {
+                return pdfNewView.currentPageIndex > 0
+            }
+        case .NextPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                return pdfOldView.currentPageIndex < pdfOldView.document.pageCount - 1
+            } else if toolbar.filePath == document.documentURL.path {
+                return pdfNewView.currentPageIndex < pdfNewView.document.pageCount - 1
+            }
+        default:
+            return true
+        }
+        return true
+    }
+
+    func compareToolbar(_ toolbar: KMCompareToolbar, didClickWithType type: CPDFCompareToolbarAction) {
+        switch type {
+        case .Increase:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                if pdfOldView.canZoomIn {
+                    pdfOldView.setScaleFactor(pdfOldView.scaleFactor + 0.2, animated: true)
+                }
+            } else if toolbar.filePath == document.documentURL.path {
+                if pdfNewView.canZoomIn {
+                    pdfNewView.setScaleFactor(pdfNewView.scaleFactor + 0.2, animated: true)
+                }
+            }
+        case .Reduce:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                if pdfOldView.canZoomOut {
+                    pdfOldView.setScaleFactor(pdfOldView.scaleFactor - 0.2, animated: true)
+                }
+            } else if toolbar.filePath == document.documentURL.path {
+                if pdfNewView.canZoomOut {
+                    pdfNewView.setScaleFactor(pdfNewView.scaleFactor - 0.2, animated: true)
+                }
+            }
+        case .FirstPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                isToolbarAction = true
+                pdfOldView.go(toPageIndex: 0, animated: false)
+            } else if toolbar.filePath == document.documentURL.path {
+                isToolbarAction = true
+                pdfNewView.go(toPageIndex: 0, animated: false)
+            }
+        case .LastPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                isToolbarAction = true
+                pdfOldView.go(toPageIndex: Int(pdfOldView.document.pageCount) - 1, animated: false)
+            } else if toolbar.filePath == document.documentURL.path {
+                isToolbarAction = true
+                pdfNewView.go(toPageIndex: Int(pdfNewView.document.pageCount) - 1, animated: false)
+            }
+        case .PreviousPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                isToolbarAction = true
+                pdfOldView.go(toPageIndex: Int(pdfOldView.currentPageIndex) - 1, animated: false)
+            } else if toolbar.filePath == document.documentURL.path {
+                isToolbarAction = true
+                pdfNewView.go(toPageIndex: Int(pdfNewView.currentPageIndex) - 1, animated: false)
+            }
+        case .NextPage:
+            if toolbar.filePath == oldDocument.documentURL.path {
+                isToolbarAction = true
+                pdfOldView.go(toPageIndex: Int(pdfOldView.currentPageIndex) + 1, animated: false)
+            } else if toolbar.filePath == document.documentURL.path {
+                isToolbarAction = true
+                pdfNewView.go(toPageIndex: Int(pdfNewView.currentPageIndex) + 1, animated: false)
+            }
+        case .Close:
+            compareManager.showToolbar = false
+            refreshToolbarInfoState()
+        case .None:
+            break
+        }
+
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+            self.isToolbarAction = false
+        }
+    }
+
+    func compareToolbar(_ toolbar: KMCompareToolbar, didGotoPage page: Int) {
+        if toolbar.filePath == oldDocument.documentURL.path {
+            pdfOldView.go(toPageIndex: Int(page), animated: false)
+        } else if toolbar.filePath == document.documentURL.path {
+            pdfNewView.go(toPageIndex: Int(page), animated: false)
+        }
+    }
+
+    // MARK: - CPDFCompareThumbVCDelegate
+    func compareThumbViewDidItemClicked(_ controller: KMCompareThumbView) {
+        if compareManager.isSyncScroll {
+            if pdfOldView.document.pageCount > compareManager.pdfSelectedIndex {
+                pdfOldView.go(toPageIndex: Int(compareManager.pdfSelectedIndex), animated: false)
+            } else {
+                pdfOldView.goToLastPage(nil)
+            }
+            if pdfNewView.document.pageCount > compareManager.pdfSelectedIndex {
+                pdfNewView.go(toPageIndex: Int(compareManager.pdfSelectedIndex), animated: false)
+            } else {
+                pdfNewView.goToLastPage(nil)
+            }
+        } else {
+            if compareManager.isSelectedOldPDF {
+                if pdfOldView.document.pageCount > compareManager.pdfSelectedIndex {
+                    pdfOldView.go(toPageIndex: Int(compareManager.pdfSelectedIndex), animated: false)
+                }
+            } else {
+                if pdfNewView.document.pageCount > compareManager.pdfSelectedIndex {
+                    pdfNewView.go(toPageIndex: Int(compareManager.pdfSelectedIndex), animated: false)
+                }
+            }
+        }
+    }
+
+    // MARK: - CPDFCompareTextVCDelegate
+
+    func compareTextView(_ controller: KMCompareTextView, didSelectedResult compareResult: CPDFCompareResult) {
+        let result = compareResult
+        let oldRect = result.oldBounds
+        let rect = result.newBounds
+
+        let pdfNewDocument = pdfNewView.document
+        let pdfOldDocument = pdfOldView.document
+
+        let page = pdfNewDocument!.page(at: UInt(result.newPageIndex()))
+        let oldPage = pdfOldDocument!.page(at: UInt(result.oldPageIndex()))
+        let selection = CPDFSelection(page: page, rect: rect())
+        let oldSelection = CPDFSelection(page: oldPage, rect: oldRect())
+
+        if compareResult.type() == .delete {
+            pdfNewView.setHighlightedSelection(nil, animated: true)
+
+            pdfOldView.go(to: oldPage)
+            pdfOldView.go(to: oldSelection, animated: true)
+            pdfOldView.setHighlight(oldSelection, forBorderColor: NSColor.red, fill: NSColor.clear, animated: true)
+        } else if compareResult.type() == .insert {
+            pdfNewView.go(to: page)
+            pdfNewView.go(to: selection, animated: true)
+            pdfNewView.setHighlight(selection, forBorderColor: NSColor.red, fill: NSColor.clear, animated: true)
+
+            pdfOldView.setHighlightedSelection(nil, animated: true)
+        } else {
+            pdfOldView.go(to: oldPage)
+            pdfOldView.go(to: oldSelection, animated: true)
+            pdfOldView.setHighlight(oldSelection, forBorderColor: NSColor.red, fill: NSColor.clear, animated: true)
+
+            pdfNewView.go(to: page)
+            pdfNewView.go(to: selection, animated: true)
+            pdfNewView.setHighlight(selection, forBorderColor: NSColor.red, fill: NSColor.clear, animated: true)
+        }
+    }
+
+    @objc func oldPDFViewboundsDidChangeNotification(_ notification: Notification) {
+        guard !self.compareManager.isSyncScroll else { return }
+        guard !self.compareManager.isThumbItemClicked else { return }
+        guard !self.isToolbarAction else { return }
+
+        if !self.isOldFileFirst && !self.isNewFileFirst {
+            self.pdfoldViewSPoint = self.pdfOldView.documentView().documentVisibleRect.origin 
+            self.pdfnewViewSPoint = self.pdfNewView.documentView().documentVisibleRect.origin
+            self.isOldFileFirst = true
+        }
+
+        if self.isOldFileFirst {
+            let pointY = self.pdfOldView.documentView().documentVisibleRect.origin.y
+            var offsetY = pointY - self.pdfoldViewSPoint.y
+
+            if self.oldToNewPDFScale > 0 {
+                offsetY = offsetY / self.oldToNewPDFScale
+            }
+
+            self.pdfNewView.documentView().contentView.scroll(NSPoint(x: self.pdfnewViewSPoint.x, y: self.pdfnewViewSPoint.y + offsetY))
+
+            NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(scrollFinishEvent), object: nil)
+            self.perform(#selector(scrollFinishEvent), with: nil, afterDelay: 0.25)
+        }
+    }
+
+    @objc func newPDFViewboundsDidChangeNotification(_ notification: Notification) {
+        guard !self.compareManager.isSyncScroll else { return }
+        guard !self.compareManager.isThumbItemClicked else { return }
+        guard !self.isToolbarAction else { return }
+
+        if !self.isOldFileFirst && !self.isNewFileFirst {
+            self.pdfoldViewSPoint = self.pdfOldView.documentView().documentVisibleRect.origin
+            self.pdfnewViewSPoint = self.pdfNewView.documentView().documentVisibleRect.origin
+
+            self.isNewFileFirst = true
+        }
+
+        if self.isNewFileFirst {
+            let pointY = self.pdfNewView.documentView().documentVisibleRect.origin.y
+            var offsetY = pointY - self.pdfnewViewSPoint.y
+
+            if self.oldToNewPDFScale > 0 {
+                offsetY = offsetY * self.oldToNewPDFScale
+            }
+
+            self.pdfOldView.documentView().contentView.scroll(NSPoint(x: self.pdfoldViewSPoint.x, y: self.pdfoldViewSPoint.y + offsetY))
+
+            NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(scrollFinishEvent), object: nil)
+            self.perform(#selector(scrollFinishEvent), with: nil, afterDelay: 0.25)
+        }
+    }
+
+    @objc func scrollFinishEvent() {
+        self.isNewFileFirst = false
+        self.isOldFileFirst = false
+    }
+
+    
+}
+

+ 381 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareContentView.xib

@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareContentView" customModule="PDF_Master" customModuleProvider="target"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="978" height="555"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="enH-LA-Xan">
+                    <rect key="frame" x="0.0" y="0.0" width="978" height="555"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="HAi-I9-D1R">
+                            <rect key="frame" x="256" y="515" width="722" height="40"/>
+                            <subviews>
+                                <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="TQF-aZ-cfG">
+                                    <rect key="frame" x="0.0" y="0.0" width="722" height="40"/>
+                                    <view key="contentView" id="DeK-NA-UHB">
+                                        <rect key="frame" x="0.0" y="0.0" width="722" height="40"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="Mer-hj-DtP">
+                                                <rect key="frame" x="199" y="12" width="63" height="16"/>
+                                                <subviews>
+                                                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="i5p-aZ-gSD">
+                                                        <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="width" constant="16" id="6vA-sb-W5p"/>
+                                                            <constraint firstAttribute="height" constant="16" id="Q8E-5i-SuS"/>
+                                                        </constraints>
+                                                    </customView>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kAD-ZH-aTT">
+                                                        <rect key="frame" x="22" y="1" width="41" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="clipping" title="Delete" id="Znf-rZ-wpu">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstItem="i5p-aZ-gSD" firstAttribute="top" secondItem="Mer-hj-DtP" secondAttribute="top" id="35G-as-7VK"/>
+                                                    <constraint firstItem="i5p-aZ-gSD" firstAttribute="leading" secondItem="Mer-hj-DtP" secondAttribute="leading" id="IRs-ve-yTV"/>
+                                                    <constraint firstItem="kAD-ZH-aTT" firstAttribute="centerY" secondItem="Mer-hj-DtP" secondAttribute="centerY" id="Uvh-OO-cNx"/>
+                                                    <constraint firstAttribute="trailing" secondItem="kAD-ZH-aTT" secondAttribute="trailing" constant="2" id="V8k-Jp-ukA"/>
+                                                    <constraint firstItem="kAD-ZH-aTT" firstAttribute="leading" secondItem="i5p-aZ-gSD" secondAttribute="trailing" constant="8" id="ab0-3Z-vHy"/>
+                                                    <constraint firstAttribute="height" constant="16" id="ctI-91-qJu"/>
+                                                </constraints>
+                                            </customView>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="Xh5-Ec-mSJ">
+                                                <rect key="frame" x="16" y="12" width="72" height="16"/>
+                                                <subviews>
+                                                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="ros-rq-YbA">
+                                                        <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="width" constant="16" id="GJ8-Kb-ciM"/>
+                                                            <constraint firstAttribute="height" constant="16" id="OXP-5B-Y7r"/>
+                                                        </constraints>
+                                                    </customView>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="06X-mq-rC3">
+                                                        <rect key="frame" x="22" y="1" width="50" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="clipping" title="Replace" id="Kcc-7O-omu">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstItem="ros-rq-YbA" firstAttribute="leading" secondItem="Xh5-Ec-mSJ" secondAttribute="leading" id="3TK-9E-ruB"/>
+                                                    <constraint firstAttribute="trailing" secondItem="06X-mq-rC3" secondAttribute="trailing" constant="2" id="KaR-qj-lDb"/>
+                                                    <constraint firstAttribute="height" constant="16" id="U7G-29-Vic"/>
+                                                    <constraint firstItem="06X-mq-rC3" firstAttribute="centerY" secondItem="Xh5-Ec-mSJ" secondAttribute="centerY" id="cey-ed-fMP"/>
+                                                    <constraint firstItem="ros-rq-YbA" firstAttribute="top" secondItem="Xh5-Ec-mSJ" secondAttribute="top" id="lS9-5k-5GG"/>
+                                                    <constraint firstItem="06X-mq-rC3" firstAttribute="leading" secondItem="ros-rq-YbA" secondAttribute="trailing" constant="8" id="snb-Lw-w8u"/>
+                                                </constraints>
+                                            </customView>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="9I4-eO-nQg">
+                                                <rect key="frame" x="114" y="12" width="59" height="16"/>
+                                                <subviews>
+                                                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="clT-xS-bT5">
+                                                        <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="width" constant="16" id="DWQ-v4-xcL"/>
+                                                            <constraint firstAttribute="height" constant="16" id="KVW-mV-6VA"/>
+                                                        </constraints>
+                                                    </customView>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lxF-Qt-SYJ">
+                                                        <rect key="frame" x="22" y="1" width="37" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="clipping" title="Insert" id="iyG-3r-f73">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstItem="clT-xS-bT5" firstAttribute="top" secondItem="9I4-eO-nQg" secondAttribute="top" id="1aq-Wt-BTb"/>
+                                                    <constraint firstAttribute="trailing" secondItem="lxF-Qt-SYJ" secondAttribute="trailing" constant="2" id="RIj-IT-xdX"/>
+                                                    <constraint firstAttribute="height" constant="16" id="mgM-sq-vYo"/>
+                                                    <constraint firstItem="lxF-Qt-SYJ" firstAttribute="leading" secondItem="clT-xS-bT5" secondAttribute="trailing" constant="8" id="oaI-j3-m5O"/>
+                                                    <constraint firstItem="lxF-Qt-SYJ" firstAttribute="centerY" secondItem="9I4-eO-nQg" secondAttribute="centerY" id="t0E-BO-3Gd"/>
+                                                    <constraint firstItem="clT-xS-bT5" firstAttribute="leading" secondItem="9I4-eO-nQg" secondAttribute="leading" id="ug6-hZ-mM2"/>
+                                                </constraints>
+                                            </customView>
+                                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="toO-bI-rn2">
+                                                <rect key="frame" x="407" y="11" width="119" height="18"/>
+                                                <buttonCell key="cell" type="check" title="Bottom Toolbar" bezelStyle="regularSquare" imagePosition="left" inset="2" id="TX5-f9-faX">
+                                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+                                                    <font key="font" metaFont="system"/>
+                                                </buttonCell>
+                                            </button>
+                                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="RXZ-fa-Reb">
+                                                <rect key="frame" x="299" y="11" width="94" height="18"/>
+                                                <buttonCell key="cell" type="check" title="Scroll Sync" bezelStyle="regularSquare" imagePosition="left" inset="2" id="K5f-Y2-PsK">
+                                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+                                                    <font key="font" metaFont="system"/>
+                                                </buttonCell>
+                                            </button>
+                                            <box boxType="custom" borderWidth="0.0" cornerRadius="2" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="HQF-3N-PR9">
+                                                <rect key="frame" x="632" y="7" width="74" height="26"/>
+                                                <view key="contentView" id="QpR-mk-aVh">
+                                                    <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                    <subviews>
+                                                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SPq-Jh-dsG">
+                                                            <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                            <buttonCell key="cell" type="bevel" title="Save" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="M2w-Oy-RMV">
+                                                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                                <font key="font" metaFont="system"/>
+                                                            </buttonCell>
+                                                            <connections>
+                                                                <action selector="saveAction:" target="-2" id="mPG-LP-P6c"/>
+                                                            </connections>
+                                                        </button>
+                                                    </subviews>
+                                                    <constraints>
+                                                        <constraint firstAttribute="bottom" secondItem="SPq-Jh-dsG" secondAttribute="bottom" id="5yn-w7-bo7"/>
+                                                        <constraint firstItem="SPq-Jh-dsG" firstAttribute="leading" secondItem="QpR-mk-aVh" secondAttribute="leading" id="6kX-5y-sUJ"/>
+                                                        <constraint firstItem="SPq-Jh-dsG" firstAttribute="top" secondItem="QpR-mk-aVh" secondAttribute="top" id="Rrc-El-DKh"/>
+                                                        <constraint firstAttribute="trailing" secondItem="SPq-Jh-dsG" secondAttribute="trailing" id="pds-L5-ntr"/>
+                                                    </constraints>
+                                                </view>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="26" id="3qd-Ol-8sC"/>
+                                                    <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="74" id="6Nn-Ms-5Gz"/>
+                                                </constraints>
+                                                <color key="fillColor" name="KMColor_Interactive_A0"/>
+                                            </box>
+                                            <box boxType="custom" borderWidth="0.0" cornerRadius="2" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="9xn-Ns-cVE">
+                                                <rect key="frame" x="542" y="7" width="74" height="26"/>
+                                                <view key="contentView" id="XWk-HQ-wGe">
+                                                    <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                    <subviews>
+                                                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hk1-Sk-Iqi">
+                                                            <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                            <buttonCell key="cell" type="bevel" title="Close" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="3AU-zl-OIh">
+                                                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                                <font key="font" metaFont="system"/>
+                                                            </buttonCell>
+                                                            <connections>
+                                                                <action selector="closeAction:" target="-2" id="1cT-Pp-caK"/>
+                                                            </connections>
+                                                        </button>
+                                                    </subviews>
+                                                    <constraints>
+                                                        <constraint firstAttribute="bottom" secondItem="hk1-Sk-Iqi" secondAttribute="bottom" id="22M-Ao-VFH"/>
+                                                        <constraint firstAttribute="trailing" secondItem="hk1-Sk-Iqi" secondAttribute="trailing" id="5xa-aL-HOC"/>
+                                                        <constraint firstAttribute="bottom" secondItem="hk1-Sk-Iqi" secondAttribute="bottom" id="EXF-5q-qIv"/>
+                                                        <constraint firstItem="hk1-Sk-Iqi" firstAttribute="top" secondItem="XWk-HQ-wGe" secondAttribute="top" id="bcH-T0-anp"/>
+                                                        <constraint firstItem="hk1-Sk-Iqi" firstAttribute="leading" secondItem="XWk-HQ-wGe" secondAttribute="leading" id="j1e-E5-lDQ"/>
+                                                        <constraint firstItem="hk1-Sk-Iqi" firstAttribute="top" secondItem="XWk-HQ-wGe" secondAttribute="top" id="s5O-Wf-WTx"/>
+                                                        <constraint firstAttribute="trailing" secondItem="hk1-Sk-Iqi" secondAttribute="trailing" id="txq-pk-l5Z"/>
+                                                        <constraint firstItem="hk1-Sk-Iqi" firstAttribute="leading" secondItem="XWk-HQ-wGe" secondAttribute="leading" id="zc8-Os-rPy"/>
+                                                    </constraints>
+                                                </view>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="74" id="MU5-Qi-xx7"/>
+                                                    <constraint firstAttribute="height" constant="26" id="USt-a1-ATH"/>
+                                                </constraints>
+                                                <color key="fillColor" name="KMColor_Interactive_A0"/>
+                                            </box>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstItem="Xh5-Ec-mSJ" firstAttribute="centerY" secondItem="DeK-NA-UHB" secondAttribute="centerY" id="0fQ-l0-W5H"/>
+                                            <constraint firstItem="9I4-eO-nQg" firstAttribute="centerY" secondItem="DeK-NA-UHB" secondAttribute="centerY" id="CVj-Np-fQk"/>
+                                            <constraint firstItem="Mer-hj-DtP" firstAttribute="centerY" secondItem="DeK-NA-UHB" secondAttribute="centerY" id="H6d-cR-nCd"/>
+                                            <constraint firstItem="HQF-3N-PR9" firstAttribute="leading" secondItem="9xn-Ns-cVE" secondAttribute="trailing" constant="16" id="I5Z-x7-SwW"/>
+                                            <constraint firstItem="toO-bI-rn2" firstAttribute="leading" secondItem="RXZ-fa-Reb" secondAttribute="trailing" constant="16" id="KOq-YT-0mB"/>
+                                            <constraint firstItem="RXZ-fa-Reb" firstAttribute="centerY" secondItem="DeK-NA-UHB" secondAttribute="centerY" id="SP1-lI-w4n"/>
+                                            <constraint firstItem="toO-bI-rn2" firstAttribute="centerY" secondItem="DeK-NA-UHB" secondAttribute="centerY" id="X4x-7N-0m7"/>
+                                            <constraint firstItem="Mer-hj-DtP" firstAttribute="leading" secondItem="9I4-eO-nQg" secondAttribute="trailing" constant="26" id="j05-Ye-lQH"/>
+                                            <constraint firstItem="HQF-3N-PR9" firstAttribute="centerY" secondItem="DeK-NA-UHB" secondAttribute="centerY" id="kES-a7-F2B"/>
+                                            <constraint firstItem="Xh5-Ec-mSJ" firstAttribute="leading" secondItem="DeK-NA-UHB" secondAttribute="leading" constant="16" id="kes-eL-nnC"/>
+                                            <constraint firstAttribute="trailing" secondItem="HQF-3N-PR9" secondAttribute="trailing" constant="16" id="kik-vL-mQe"/>
+                                            <constraint firstItem="HQF-3N-PR9" firstAttribute="leading" secondItem="toO-bI-rn2" secondAttribute="trailing" constant="106" id="uOO-9j-5ZJ"/>
+                                            <constraint firstItem="9xn-Ns-cVE" firstAttribute="centerY" secondItem="DeK-NA-UHB" secondAttribute="centerY" id="ui7-Cd-BUi"/>
+                                            <constraint firstItem="9I4-eO-nQg" firstAttribute="leading" secondItem="Xh5-Ec-mSJ" secondAttribute="trailing" constant="26" id="yPO-he-9jU"/>
+                                        </constraints>
+                                    </view>
+                                    <color key="fillColor" name="KMColor_Layout_L0"/>
+                                </box>
+                            </subviews>
+                            <constraints>
+                                <constraint firstAttribute="trailing" secondItem="TQF-aZ-cfG" secondAttribute="trailing" id="5d5-Lh-QCz"/>
+                                <constraint firstItem="TQF-aZ-cfG" firstAttribute="top" secondItem="HAi-I9-D1R" secondAttribute="top" id="Piq-Fe-VMt"/>
+                                <constraint firstAttribute="bottom" secondItem="TQF-aZ-cfG" secondAttribute="bottom" id="Xkt-fK-9D8"/>
+                                <constraint firstItem="TQF-aZ-cfG" firstAttribute="leading" secondItem="HAi-I9-D1R" secondAttribute="leading" id="laf-G2-wjc"/>
+                                <constraint firstAttribute="height" constant="40" id="mna-iH-b30"/>
+                            </constraints>
+                        </customView>
+                        <splitView arrangesAllSubviews="NO" dividerStyle="paneSplitter" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xlx-BI-eQe">
+                            <rect key="frame" x="256" y="0.0" width="722" height="515"/>
+                            <subviews>
+                                <customView fixedFrame="YES" id="unf-RV-4ED">
+                                    <rect key="frame" x="0.0" y="0.0" width="449" height="515"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2bj-7t-Pqy" customClass="CPDFView">
+                                            <rect key="frame" x="0.0" y="0.0" width="449" height="515"/>
+                                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        </customView>
+                                    </subviews>
+                                </customView>
+                                <customView fixedFrame="YES" id="T6k-LL-ixO">
+                                    <rect key="frame" x="459" y="0.0" width="263" height="515"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <customView id="9Xp-iZ-yRD" customClass="CPDFView">
+                                            <rect key="frame" x="0.0" y="0.0" width="263" height="515"/>
+                                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        </customView>
+                                    </subviews>
+                                </customView>
+                            </subviews>
+                            <holdingPriorities>
+                                <real value="250"/>
+                                <real value="250"/>
+                            </holdingPriorities>
+                        </splitView>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="pdh-Qu-PeL">
+                            <rect key="frame" x="0.0" y="0.0" width="256" height="555"/>
+                            <subviews>
+                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="0Ql-ZN-9ws">
+                                    <rect key="frame" x="0.0" y="523" width="256" height="32"/>
+                                    <subviews>
+                                        <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="rLb-Xm-Ola">
+                                            <rect key="frame" x="0.0" y="0.0" width="128" height="32"/>
+                                            <view key="contentView" id="Eub-GW-VzK">
+                                                <rect key="frame" x="0.0" y="0.0" width="128" height="32"/>
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                <subviews>
+                                                    <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Xzm-dN-5BO">
+                                                        <rect key="frame" x="56" y="8" width="16" height="16"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="height" constant="16" id="bcf-FU-DCh"/>
+                                                            <constraint firstAttribute="width" constant="16" id="qfE-1u-Qxg"/>
+                                                        </constraints>
+                                                        <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="ic_sidetabbar_thumbnail_white_nor" id="X6n-W9-lYr"/>
+                                                    </imageView>
+                                                    <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="D8F-Aj-Obd">
+                                                        <rect key="frame" x="0.0" y="0.0" width="128" height="32"/>
+                                                        <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="26a-le-KNp">
+                                                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                            <font key="font" metaFont="system"/>
+                                                        </buttonCell>
+                                                    </button>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstItem="Xzm-dN-5BO" firstAttribute="centerY" secondItem="Eub-GW-VzK" secondAttribute="centerY" id="J9P-jL-Aho"/>
+                                                    <constraint firstAttribute="bottom" secondItem="D8F-Aj-Obd" secondAttribute="bottom" id="WYm-zG-G00"/>
+                                                    <constraint firstItem="Xzm-dN-5BO" firstAttribute="centerX" secondItem="Eub-GW-VzK" secondAttribute="centerX" id="Y29-IT-1jX"/>
+                                                    <constraint firstItem="D8F-Aj-Obd" firstAttribute="top" secondItem="Eub-GW-VzK" secondAttribute="top" id="dh2-0v-AF4"/>
+                                                    <constraint firstItem="D8F-Aj-Obd" firstAttribute="leading" secondItem="Eub-GW-VzK" secondAttribute="leading" id="kPz-p9-lQn"/>
+                                                    <constraint firstAttribute="trailing" secondItem="D8F-Aj-Obd" secondAttribute="trailing" id="wiz-yI-4Vn"/>
+                                                </constraints>
+                                            </view>
+                                        </box>
+                                        <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="c73-Nt-SfP">
+                                            <rect key="frame" x="128" y="0.0" width="128" height="32"/>
+                                            <view key="contentView" id="xE5-Rb-2ae">
+                                                <rect key="frame" x="0.0" y="0.0" width="128" height="32"/>
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                <subviews>
+                                                    <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="CwF-Nq-cNN">
+                                                        <rect key="frame" x="56" y="8" width="16" height="16"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="width" constant="16" id="Uah-LJ-aY6"/>
+                                                            <constraint firstAttribute="height" constant="16" id="hpd-YR-J39"/>
+                                                        </constraints>
+                                                        <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="ic_compare_result_text" id="hyK-iS-89d"/>
+                                                    </imageView>
+                                                    <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qc0-e0-bsm">
+                                                        <rect key="frame" x="0.0" y="0.0" width="128" height="32"/>
+                                                        <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="ZgG-GJ-fiz">
+                                                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                            <font key="font" metaFont="system"/>
+                                                        </buttonCell>
+                                                    </button>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstAttribute="trailing" secondItem="qc0-e0-bsm" secondAttribute="trailing" id="4XH-Sm-b5E"/>
+                                                    <constraint firstItem="qc0-e0-bsm" firstAttribute="leading" secondItem="xE5-Rb-2ae" secondAttribute="leading" id="GTT-zS-gxp"/>
+                                                    <constraint firstItem="CwF-Nq-cNN" firstAttribute="centerY" secondItem="xE5-Rb-2ae" secondAttribute="centerY" id="SUR-6J-mmH"/>
+                                                    <constraint firstItem="qc0-e0-bsm" firstAttribute="top" secondItem="xE5-Rb-2ae" secondAttribute="top" id="Xlx-YA-8wl"/>
+                                                    <constraint firstAttribute="bottom" secondItem="qc0-e0-bsm" secondAttribute="bottom" id="nNp-al-n7T"/>
+                                                    <constraint firstItem="CwF-Nq-cNN" firstAttribute="centerX" secondItem="xE5-Rb-2ae" secondAttribute="centerX" id="rCh-bk-Scx"/>
+                                                </constraints>
+                                            </view>
+                                        </box>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="rLb-Xm-Ola" firstAttribute="top" secondItem="0Ql-ZN-9ws" secondAttribute="top" id="7Uh-G3-rkX"/>
+                                        <constraint firstAttribute="trailing" secondItem="c73-Nt-SfP" secondAttribute="trailing" id="A5V-d9-AIr"/>
+                                        <constraint firstAttribute="bottom" secondItem="rLb-Xm-Ola" secondAttribute="bottom" id="BeB-h5-kr8"/>
+                                        <constraint firstAttribute="height" constant="32" id="HWt-W8-1Ku"/>
+                                        <constraint firstAttribute="bottom" secondItem="c73-Nt-SfP" secondAttribute="bottom" id="N6C-kA-Pun"/>
+                                        <constraint firstItem="rLb-Xm-Ola" firstAttribute="width" secondItem="0Ql-ZN-9ws" secondAttribute="width" multiplier="0.5" id="Qvs-gQ-aa4"/>
+                                        <constraint firstItem="c73-Nt-SfP" firstAttribute="top" secondItem="0Ql-ZN-9ws" secondAttribute="top" id="WUD-rW-H1J"/>
+                                        <constraint firstItem="c73-Nt-SfP" firstAttribute="width" secondItem="0Ql-ZN-9ws" secondAttribute="width" multiplier="0.5" id="jg2-H1-g8R"/>
+                                        <constraint firstItem="rLb-Xm-Ola" firstAttribute="leading" secondItem="0Ql-ZN-9ws" secondAttribute="leading" id="pcs-RX-IMe"/>
+                                    </constraints>
+                                </customView>
+                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="zCZ-2v-uFU">
+                                    <rect key="frame" x="0.0" y="0.0" width="256" height="523"/>
+                                </customView>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="zCZ-2v-uFU" firstAttribute="leading" secondItem="pdh-Qu-PeL" secondAttribute="leading" id="NXn-eb-Fc0"/>
+                                <constraint firstAttribute="width" constant="256" id="NrC-WC-2Lc"/>
+                                <constraint firstItem="zCZ-2v-uFU" firstAttribute="top" secondItem="0Ql-ZN-9ws" secondAttribute="bottom" id="UKi-pq-ZOM"/>
+                                <constraint firstItem="0Ql-ZN-9ws" firstAttribute="top" secondItem="pdh-Qu-PeL" secondAttribute="top" id="ZQc-bu-EMu"/>
+                                <constraint firstAttribute="bottom" secondItem="zCZ-2v-uFU" secondAttribute="bottom" id="pFq-wP-hZh"/>
+                                <constraint firstItem="0Ql-ZN-9ws" firstAttribute="leading" secondItem="pdh-Qu-PeL" secondAttribute="leading" id="qf5-BM-cVl"/>
+                                <constraint firstAttribute="trailing" secondItem="zCZ-2v-uFU" secondAttribute="trailing" id="rfI-Gt-xry"/>
+                                <constraint firstAttribute="trailing" secondItem="0Ql-ZN-9ws" secondAttribute="trailing" id="wRX-6g-GeG"/>
+                            </constraints>
+                        </customView>
+                    </subviews>
+                    <constraints>
+                        <constraint firstAttribute="bottom" secondItem="pdh-Qu-PeL" secondAttribute="bottom" id="19X-gK-oJU"/>
+                        <constraint firstItem="HAi-I9-D1R" firstAttribute="leading" secondItem="pdh-Qu-PeL" secondAttribute="trailing" id="1i5-uv-tti"/>
+                        <constraint firstItem="pdh-Qu-PeL" firstAttribute="top" secondItem="enH-LA-Xan" secondAttribute="top" id="2Ba-hk-mwj"/>
+                        <constraint firstItem="xlx-BI-eQe" firstAttribute="top" secondItem="HAi-I9-D1R" secondAttribute="bottom" id="9Sq-fS-G5K"/>
+                        <constraint firstItem="HAi-I9-D1R" firstAttribute="top" secondItem="enH-LA-Xan" secondAttribute="top" id="D66-qc-ZYL"/>
+                        <constraint firstAttribute="bottom" secondItem="xlx-BI-eQe" secondAttribute="bottom" id="Hhe-fp-iWE"/>
+                        <constraint firstAttribute="trailing" secondItem="xlx-BI-eQe" secondAttribute="trailing" id="fkD-xk-yOu"/>
+                        <constraint firstItem="pdh-Qu-PeL" firstAttribute="leading" secondItem="enH-LA-Xan" secondAttribute="leading" id="fxG-gr-Zl7"/>
+                        <constraint firstAttribute="trailing" secondItem="HAi-I9-D1R" secondAttribute="trailing" id="kUf-Pc-0g4"/>
+                        <constraint firstItem="xlx-BI-eQe" firstAttribute="leading" secondItem="pdh-Qu-PeL" secondAttribute="trailing" id="kZu-we-eZD"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="enH-LA-Xan" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="QQE-Ux-hXH"/>
+                <constraint firstItem="enH-LA-Xan" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="hZh-Yu-y3k"/>
+                <constraint firstAttribute="trailing" secondItem="enH-LA-Xan" secondAttribute="trailing" id="p9f-mp-OB5"/>
+                <constraint firstAttribute="bottom" secondItem="enH-LA-Xan" secondAttribute="bottom" id="re7-XP-WkB"/>
+            </constraints>
+            <point key="canvasLocation" x="248" y="206.5"/>
+        </customView>
+    </objects>
+    <resources>
+        <image name="ic_compare_result_text" width="16" height="16"/>
+        <image name="ic_sidetabbar_thumbnail_white_nor" width="16" height="16"/>
+        <namedColor name="KMColor_Interactive_A0">
+            <color red="0.28627450980392155" green="0.50980392156862742" blue="0.90196078431372551" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+        <namedColor name="KMColor_Layout_L0">
+            <color red="0.9882352941176471" green="0.99215686274509807" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>

+ 132 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareToolbar.swift

@@ -0,0 +1,132 @@
+//
+//  KMCompareToolbar.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+protocol KMCompareToolbarDelegate: AnyObject {
+    func compareToolbar(_ toolbar: KMCompareToolbar, didClickWithType type: CPDFCompareToolbarAction)
+    func compareToolbar(_ toolbar: KMCompareToolbar, didGotoPage page: Int)
+    func compareToolbar(_ toolbar: KMCompareToolbar, didActionEnable action: CPDFCompareToolbarAction) -> Bool
+}
+
+enum CPDFCompareToolbarAction {
+    case None
+    case Increase
+    case Reduce
+    case FirstPage
+    case LastPage
+    case PreviousPage
+    case NextPage
+    case Close
+}
+
+class KMCompareToolbar: KMBaseXibView {
+
+    @IBOutlet weak var contendView: NSView!
+    @IBOutlet weak var reduceBtn: NSButton!
+    @IBOutlet weak var increaseBtn: NSButton!
+    @IBOutlet weak var firstPageBtn: NSButton!
+    @IBOutlet weak var lastPageBtn: NSButton!
+    @IBOutlet weak var currentPageTF: NSTextField!
+    @IBOutlet weak var totalPageLabel: NSTextField!
+    @IBOutlet weak var previousPageBtn: NSButton!
+    @IBOutlet weak var nextPageBtn: NSButton!
+    @IBOutlet weak var closeBtn: NSButton!
+    @IBOutlet weak var curPageBox: NSBox!
+    
+    weak var delegate: KMCompareToolbarDelegate?
+
+    var filePath: String = ""
+    var currentPage: Int = 0 {
+        didSet {
+            currentPageTF.stringValue = "\(currentPage + 1)"
+        }
+    }
+    var totalPage: Int = 0 {
+        didSet {
+            totalPageLabel.stringValue = "\(totalPage)"
+        }
+    }
+
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        wantsLayer = true
+        layer?.backgroundColor = NSColor.white.cgColor
+
+        curPageBox.borderColor = NSColor(red: 218/255.0, green: 219/255.0, blue: 222/255.0, alpha: 1.0)
+        curPageBox.fillColor = NSColor.white
+
+        totalPageLabel.textColor = NSColor(red: 117/255.0, green: 119/255.0, blue: 128/255.0, alpha: 1.0)
+
+        currentPageTF.textColor = NSColor(red: 14/255.0, green: 17/255.0, blue: 20/255.0, alpha: 1.0)
+        currentPageTF.wantsLayer = true
+        currentPageTF.backgroundColor = NSColor.clear
+        currentPageTF.drawsBackground = false
+        currentPageTF.isBordered = false
+        currentPageTF.layer?.backgroundColor = NSColor.clear.cgColor
+        currentPageTF.formatter = TextFieldFormatter()
+        currentPageTF.delegate = self
+
+        refreshButtonState()
+    }
+
+    func refreshButtonState() {
+        increaseBtn.isEnabled = delegate?.compareToolbar(self, didActionEnable: .Increase) ?? true
+        reduceBtn.isEnabled = delegate?.compareToolbar(self, didActionEnable: .Reduce) ?? true
+        firstPageBtn.isEnabled = delegate?.compareToolbar(self, didActionEnable: .FirstPage) ?? true
+        lastPageBtn.isEnabled = delegate?.compareToolbar(self, didActionEnable: .LastPage) ?? true
+        previousPageBtn.isEnabled = delegate?.compareToolbar(self, didActionEnable: .PreviousPage) ?? true
+        nextPageBtn.isEnabled = delegate?.compareToolbar(self, didActionEnable: .NextPage) ?? true
+    }
+
+    @IBAction func buttonAction(_ sender: NSButton) {
+        var action: CPDFCompareToolbarAction = .None
+
+        switch sender {
+        case increaseBtn:
+            action = .Increase
+        case reduceBtn:
+            action = .Reduce
+        case firstPageBtn:
+            action = .FirstPage
+        case lastPageBtn:
+            action = .LastPage
+        case previousPageBtn:
+            action = .PreviousPage
+        case nextPageBtn:
+            action = .NextPage
+        case closeBtn:
+            action = .Close
+        default:
+            break
+        }
+
+        if action != .None {
+            delegate?.compareToolbar(self, didClickWithType: action)
+        }
+    }
+}
+
+extension KMCompareToolbar: NSTextFieldDelegate{
+    func controlTextDidEndEditing(_ obj: Notification) {
+        if obj.object as AnyObject === currentPageTF {
+            var index = currentPageTF.integerValue
+            if index >= totalPage {
+                index = totalPage
+                currentPage = index
+            } 
+//            else if index == 0 {
+//                self.currentPage = currentPage
+//            }
+            delegate?.compareToolbar(self, didGotoPage: index - 1)
+        }
+    }
+}

+ 264 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/KMCompareToolbar.xib

@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareToolbar" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="closeBtn" destination="Ibp-k2-bWs" id="3xu-fD-plY"/>
+                <outlet property="contendView" destination="ZXp-iu-QMR" id="LYg-hW-qwJ"/>
+                <outlet property="curPageBox" destination="660-ic-Qbt" id="BKD-Cq-yoL"/>
+                <outlet property="currentPageTF" destination="LH6-QK-DGH" id="bq8-hU-EYA"/>
+                <outlet property="firstPageBtn" destination="dYK-vd-MGl" id="2Ol-gh-5Ax"/>
+                <outlet property="increaseBtn" destination="K8q-ml-fxl" id="AaZ-Qs-NcG"/>
+                <outlet property="lastPageBtn" destination="nWR-NG-jwj" id="cZU-0j-Nv2"/>
+                <outlet property="nextPageBtn" destination="lh0-Ng-BQG" id="E2b-Br-Nro"/>
+                <outlet property="previousPageBtn" destination="hI8-3j-7Os" id="e5i-hi-5nQ"/>
+                <outlet property="reduceBtn" destination="CB7-ex-WQH" id="bqf-sa-3zE"/>
+                <outlet property="totalPageLabel" destination="tbP-KE-ctr" id="kUa-hO-0zL"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="310" height="48"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="XWZ-QA-n3P">
+                    <rect key="frame" x="0.0" y="0.0" width="310" height="48"/>
+                    <subviews>
+                        <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZXp-iu-QMR">
+                            <rect key="frame" x="0.0" y="0.0" width="310" height="48"/>
+                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="2ke-G6-Jqh">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                        </button>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="CB7-ex-WQH">
+                            <rect key="frame" x="16" y="12" width="24" height="24"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="btn_zoomin" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="kEL-L0-nTX">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="24" id="CPf-HH-OcV"/>
+                                <constraint firstAttribute="width" constant="24" id="kmI-k1-vYn"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonAction:" target="-2" id="E7K-2I-XHL"/>
+                            </connections>
+                        </button>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="K8q-ml-fxl">
+                            <rect key="frame" x="40" y="12" width="24" height="24"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="btn_zoomout" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="hL1-gg-Rkn">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="24" id="0G9-bk-H3C"/>
+                                <constraint firstAttribute="height" constant="24" id="1x6-o3-zdK"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonAction:" target="-2" id="zpl-KX-wCv"/>
+                            </connections>
+                        </button>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dYK-vd-MGl">
+                            <rect key="frame" x="80" y="12" width="24" height="24"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="btn_firstPage" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="6LA-hq-eqf">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="24" id="Ufw-z8-Uwx"/>
+                                <constraint firstAttribute="height" constant="24" id="dH0-we-Vfz"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonAction:" target="-2" id="JJ2-mX-XXj"/>
+                            </connections>
+                        </button>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nWR-NG-jwj">
+                            <rect key="frame" x="104" y="12" width="24" height="24"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="btn_lastPage" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="7ke-Ao-cbQ">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="24" id="rcb-8A-Xcg"/>
+                                <constraint firstAttribute="width" constant="24" id="zhe-Z8-LeD"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonAction:" target="-2" id="UTh-Yd-z2s"/>
+                            </connections>
+                        </button>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="hI8-3j-7Os">
+                            <rect key="frame" x="216" y="12" width="24" height="24"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="btn_previousPage" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="thy-8q-86d">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="24" id="O3y-Iq-fLR"/>
+                                <constraint firstAttribute="width" constant="24" id="P6w-sh-4xV"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonAction:" target="-2" id="TD7-O0-T7G"/>
+                            </connections>
+                        </button>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="lh0-Ng-BQG">
+                            <rect key="frame" x="240" y="12" width="24" height="24"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="btn_nextPage" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="o3n-8t-QCO">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="24" id="F2J-SU-hMO"/>
+                                <constraint firstAttribute="height" constant="24" id="xHR-hC-iXd"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonAction:" target="-2" id="r6m-cA-Ybq"/>
+                            </connections>
+                        </button>
+                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ibp-k2-bWs">
+                            <rect key="frame" x="280" y="12" width="24" height="24"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="btn_close" imagePosition="only" alignment="center" imageScaling="proportionallyDown" inset="2" id="Hih-da-0bn">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="24" id="RgE-pc-JT9"/>
+                                <constraint firstAttribute="height" constant="24" id="jmg-v3-GNh"/>
+                            </constraints>
+                            <connections>
+                                <action selector="buttonAction:" target="-2" id="4HM-Iz-scy"/>
+                            </connections>
+                        </button>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="lmF-li-kSn">
+                            <rect key="frame" x="132" y="14" width="80" height="20"/>
+                            <subviews>
+                                <box boxType="custom" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="660-ic-Qbt">
+                                    <rect key="frame" x="0.0" y="0.0" width="47" height="20"/>
+                                    <view key="contentView" id="Ekn-mv-cgC">
+                                        <rect key="frame" x="1" y="1" width="45" height="18"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <textField focusRingType="none" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LH6-QK-DGH">
+                                                <rect key="frame" x="0.0" y="1" width="45" height="16"/>
+                                                <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" focusRingType="none" alignment="center" drawsBackground="YES" id="aUI-ge-jFV">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="Color"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstItem="LH6-QK-DGH" firstAttribute="leading" secondItem="Ekn-mv-cgC" secondAttribute="leading" id="DaB-5B-KYj"/>
+                                            <constraint firstItem="LH6-QK-DGH" firstAttribute="centerY" secondItem="Ekn-mv-cgC" secondAttribute="centerY" id="gLB-Ji-bH8"/>
+                                            <constraint firstItem="LH6-QK-DGH" firstAttribute="centerX" secondItem="Ekn-mv-cgC" secondAttribute="centerX" id="ud7-uv-RuY"/>
+                                            <constraint firstAttribute="trailing" secondItem="LH6-QK-DGH" secondAttribute="trailing" id="wbg-yT-j31"/>
+                                        </constraints>
+                                    </view>
+                                    <color key="borderColor" name="Color"/>
+                                    <color key="fillColor" name="Color"/>
+                                </box>
+                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GVH-iH-XYm">
+                                    <rect key="frame" x="47" y="2" width="8" height="16"/>
+                                    <textFieldCell key="cell" lineBreakMode="clipping" title="/" id="Vl8-ed-LD5">
+                                        <font key="font" metaFont="system"/>
+                                        <color key="textColor" name="KMColor_Layout_H2"/>
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </textFieldCell>
+                                </textField>
+                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="tbP-KE-ctr">
+                                    <rect key="frame" x="53" y="2" width="27" height="16"/>
+                                    <textFieldCell key="cell" lineBreakMode="clipping" title="100" id="GNI-AK-UAi">
+                                        <font key="font" metaFont="system"/>
+                                        <color key="textColor" name="KMColor_Layout_H2"/>
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </textFieldCell>
+                                </textField>
+                            </subviews>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="20" id="By7-63-WkR"/>
+                                <constraint firstItem="tbP-KE-ctr" firstAttribute="centerY" secondItem="lmF-li-kSn" secondAttribute="centerY" id="E6h-lh-k8g"/>
+                                <constraint firstAttribute="bottom" secondItem="660-ic-Qbt" secondAttribute="bottom" id="KEZ-0F-NaR"/>
+                                <constraint firstAttribute="width" constant="80" id="L44-XU-O8d"/>
+                                <constraint firstItem="660-ic-Qbt" firstAttribute="top" secondItem="lmF-li-kSn" secondAttribute="top" id="NBj-YD-Q92"/>
+                                <constraint firstItem="tbP-KE-ctr" firstAttribute="leading" secondItem="GVH-iH-XYm" secondAttribute="trailing" constant="2" id="QqB-2R-sKd"/>
+                                <constraint firstItem="GVH-iH-XYm" firstAttribute="centerY" secondItem="lmF-li-kSn" secondAttribute="centerY" id="sAz-Es-NnV"/>
+                                <constraint firstItem="GVH-iH-XYm" firstAttribute="leading" secondItem="660-ic-Qbt" secondAttribute="trailing" constant="2" id="v36-sa-KEV"/>
+                                <constraint firstItem="660-ic-Qbt" firstAttribute="leading" secondItem="lmF-li-kSn" secondAttribute="leading" id="vUN-7o-3l0"/>
+                                <constraint firstAttribute="trailing" secondItem="tbP-KE-ctr" secondAttribute="trailing" constant="2" id="ycX-2n-h0B"/>
+                            </constraints>
+                        </customView>
+                        <box fixedFrame="YES" boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="RZh-zD-gdI">
+                            <rect key="frame" x="71" y="14" width="1" height="20"/>
+                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
+                            <view key="contentView" id="M1x-Pc-lob">
+                                <rect key="frame" x="0.0" y="0.0" width="1" height="20"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            </view>
+                            <color key="fillColor" name="KMColor_Layout_L_2"/>
+                        </box>
+                        <box fixedFrame="YES" boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="9K1-FG-kAM">
+                            <rect key="frame" x="272" y="14" width="1" height="20"/>
+                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
+                            <view key="contentView" id="Iwk-Wa-RnR">
+                                <rect key="frame" x="0.0" y="0.0" width="1" height="20"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            </view>
+                            <color key="fillColor" name="KMColor_Layout_L_2"/>
+                        </box>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="hI8-3j-7Os" firstAttribute="leading" secondItem="XWZ-QA-n3P" secondAttribute="leading" constant="216" id="7h1-qa-2jG"/>
+                        <constraint firstItem="K8q-ml-fxl" firstAttribute="centerY" secondItem="CB7-ex-WQH" secondAttribute="centerY" id="AIr-8V-jav"/>
+                        <constraint firstItem="nWR-NG-jwj" firstAttribute="leading" secondItem="dYK-vd-MGl" secondAttribute="trailing" id="Ey4-Tu-yh6"/>
+                        <constraint firstItem="CB7-ex-WQH" firstAttribute="centerY" secondItem="XWZ-QA-n3P" secondAttribute="centerY" id="J3L-2t-4cQ"/>
+                        <constraint firstItem="lmF-li-kSn" firstAttribute="leading" secondItem="XWZ-QA-n3P" secondAttribute="leading" constant="132" id="Lb1-rb-1x2"/>
+                        <constraint firstItem="dYK-vd-MGl" firstAttribute="leading" secondItem="XWZ-QA-n3P" secondAttribute="leading" constant="80" id="Q3V-9N-E8s"/>
+                        <constraint firstItem="CB7-ex-WQH" firstAttribute="leading" secondItem="XWZ-QA-n3P" secondAttribute="leading" constant="16" id="TLQ-yx-gXo"/>
+                        <constraint firstItem="lmF-li-kSn" firstAttribute="centerY" secondItem="XWZ-QA-n3P" secondAttribute="centerY" id="TYm-ga-hVI"/>
+                        <constraint firstItem="K8q-ml-fxl" firstAttribute="leading" secondItem="CB7-ex-WQH" secondAttribute="trailing" id="dV3-iZ-lmX"/>
+                        <constraint firstItem="Ibp-k2-bWs" firstAttribute="centerY" secondItem="XWZ-QA-n3P" secondAttribute="centerY" id="goi-9a-OxG"/>
+                        <constraint firstItem="lh0-Ng-BQG" firstAttribute="leading" secondItem="hI8-3j-7Os" secondAttribute="trailing" id="jrf-7d-moF"/>
+                        <constraint firstItem="nWR-NG-jwj" firstAttribute="centerY" secondItem="dYK-vd-MGl" secondAttribute="centerY" id="ofs-lU-kNC"/>
+                        <constraint firstItem="hI8-3j-7Os" firstAttribute="centerY" secondItem="XWZ-QA-n3P" secondAttribute="centerY" id="reg-vN-8MN"/>
+                        <constraint firstItem="dYK-vd-MGl" firstAttribute="centerY" secondItem="XWZ-QA-n3P" secondAttribute="centerY" id="seD-3g-PG1"/>
+                        <constraint firstItem="Ibp-k2-bWs" firstAttribute="leading" secondItem="XWZ-QA-n3P" secondAttribute="leading" constant="280" id="udT-PH-A0U"/>
+                        <constraint firstItem="lh0-Ng-BQG" firstAttribute="centerY" secondItem="XWZ-QA-n3P" secondAttribute="centerY" id="uhQ-Ab-icu"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="XWZ-QA-n3P" secondAttribute="trailing" id="gXr-9l-YfP"/>
+                <constraint firstItem="XWZ-QA-n3P" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="gdo-Gz-1tU"/>
+                <constraint firstAttribute="bottom" secondItem="XWZ-QA-n3P" secondAttribute="bottom" id="mAH-Vg-dvl"/>
+                <constraint firstItem="XWZ-QA-n3P" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="oE5-r1-ent"/>
+            </constraints>
+            <point key="canvasLocation" x="-71" y="188"/>
+        </customView>
+    </objects>
+    <resources>
+        <image name="btn_close" width="24" height="24"/>
+        <image name="btn_firstPage" width="24" height="24"/>
+        <image name="btn_lastPage" width="24" height="24"/>
+        <image name="btn_nextPage" width="24" height="24"/>
+        <image name="btn_previousPage" width="24" height="24"/>
+        <image name="btn_zoomin" width="24" height="24"/>
+        <image name="btn_zoomout" width="24" height="24"/>
+        <namedColor name="Color">
+            <color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+        <namedColor name="KMColor_Layout_H2">
+            <color red="0.45882352941176469" green="0.46666666666666667" blue="0.50196078431372548" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+        <namedColor name="KMColor_Layout_L_2">
+            <color red="0.85490196078431369" green="0.85882352941176465" blue="0.87058823529411766" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>

+ 116 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextHeaderView.swift

@@ -0,0 +1,116 @@
+//
+//  KMCompareTextHeaderView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/22.
+//
+
+import Cocoa
+
+protocol KMCompareTextHeaderViewDelegate: AnyObject {
+    func compareTextHeaderDidUpdateExpandState(_ item: KMCompareTextHeaderView)
+}
+
+
+class KMCompareTextHeaderView: NSView {
+    var contendView: NSView!
+    var expandBtn: NSButton!
+    var pageLbl: NSTextField!
+    var countLbl: NSTextField!
+
+    var resultModel: KMCompareResultModel = KMCompareResultModel()
+    weak var delegate: KMCompareTextHeaderViewDelegate?
+    
+    var itemIndex: Int = 0
+    
+    override func draw(_ dirtyRect: NSRect) {
+        super.draw(dirtyRect)
+        // Drawing code here.
+    }
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        // Additional setup if needed
+    }
+
+    func setUp() {
+        if expandBtn == nil {
+            expandBtn = NSButton(frame: NSRect(x: 0, y: 8, width: 16, height: 16))
+            expandBtn.autoresizingMask = [.maxXMargin, .minYMargin, .maxYMargin]
+            expandBtn.bezelStyle = .regularSquare
+            expandBtn.isBordered = false
+            expandBtn.target = self
+            expandBtn.action = #selector(expandBtnClicked(_:))
+        }
+        addSubview(expandBtn)
+
+        if pageLbl == nil {
+            pageLbl = NSTextField(frame: NSRect(x: 16, y: 8, width: 184, height: 16))
+            pageLbl.autoresizingMask = [.maxXMargin, .minYMargin, .maxYMargin]
+            pageLbl.isEditable = false
+            pageLbl.drawsBackground = false
+            pageLbl.isBordered = false
+            pageLbl.font = NSFont.systemFont(ofSize: 13.0)
+            pageLbl.textColor = KMAppearance.Layout.h1Color()
+            pageLbl.alignment = .left
+            pageLbl.backgroundColor = NSColor.clear
+            pageLbl.wantsLayer = true
+            pageLbl.layer?.backgroundColor = NSColor.clear.cgColor
+        }
+        pageLbl.autoresizingMask = [.maxXMargin, .minYMargin, .maxYMargin]
+        addSubview(pageLbl)
+
+        if countLbl == nil {
+            countLbl = NSTextField(frame: NSRect(x: frame.width - 54, y: 8, width: 32, height: 16))
+            countLbl.autoresizingMask = [.minXMargin, .minYMargin, .maxYMargin]
+            countLbl.isEditable = false
+            countLbl.drawsBackground = false
+            countLbl.isBordered = false
+            countLbl.font = NSFont.systemFont(ofSize: 12.0)
+            countLbl.textColor = KMAppearance.Layout.h1Color()
+            countLbl.alignment = .right
+            countLbl.backgroundColor = NSColor.clear
+            countLbl.wantsLayer = true
+            countLbl.layer?.backgroundColor = NSColor.clear.cgColor
+        }
+        countLbl.autoresizingMask = [.maxXMargin, .minYMargin, .maxYMargin]
+        addSubview(countLbl)
+    }
+
+    // MARK: - Setter
+
+    func updateUI() {
+        if resultModel.isExpand {
+            expandBtn.image = NSImage(named: "arrow_down_nor")
+            expandBtn.alternateImage = NSImage(named: "arrow_down_sel")
+        } else {
+            expandBtn.image = NSImage(named: "arrow_right_nor")
+            expandBtn.alternateImage = NSImage(named: "arrow_right_sel")
+        }
+
+        countLbl.stringValue = "\(String(describing: resultModel.results.insertCount)) + \(String(describing: resultModel.results.deleteCount)) + \(String(describing: resultModel.results.replaceCount))"
+
+        var compareResult: CPDFCompareResult?
+        if resultModel.results.textResults().count > 0 {
+            compareResult = resultModel.results.textResults().first
+        } else if resultModel.results.imageResults().count > 0 {
+            compareResult = resultModel.results.imageResults().first
+        }
+        
+        guard let compareResult = compareResult else { return }
+        if compareResult.oldPageIndex() == -1 {
+            pageLbl.stringValue = "- VS \(NSLocalizedString("Page", comment: "")) \(compareResult.newPageIndex() + 1)"
+        } else if compareResult.newPageIndex() == -1 {
+            pageLbl.stringValue = "\(NSLocalizedString("Page", comment: "")) \(compareResult.oldPageIndex() + 1) VS -"
+        } else {
+            pageLbl.stringValue = "\(NSLocalizedString("Page", comment: "")) \(compareResult.oldPageIndex() + 1) VS \(NSLocalizedString("Page", comment: "")) \(compareResult.newPageIndex() + 1)"
+        }
+    }
+
+    // MARK: - IBAction
+
+    @objc func expandBtnClicked(_ sender: NSButton) {
+        resultModel.isExpand = !resultModel.isExpand
+        delegate?.compareTextHeaderDidUpdateExpandState(self)
+    }
+}

+ 18 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextHeaderView.xib

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareTextHeaderView" customModule="PDF_Master" customModuleProvider="target"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <point key="canvasLocation" x="113" y="124"/>
+        </customView>
+    </objects>
+</document>

+ 147 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextView.swift

@@ -0,0 +1,147 @@
+//
+//  KMCompareTextView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+protocol KMCompareTextViewDelegate: AnyObject {
+    func compareTextView(_ view: KMCompareTextView, didSelectedResult compareResult: CPDFCompareResult)
+}
+
+class KMCompareTextView: KMBaseXibView, NSCollectionViewDelegateFlowLayout, NSCollectionViewDataSource, KMCompareTextViewItemDelegate, KMCompareTextHeaderViewDelegate {
+    
+    @IBOutlet weak var contendView: NSView!
+    @IBOutlet weak var infoLbl: NSTextField!
+    @IBOutlet weak var totalTitleLbl: NSTextField!
+    @IBOutlet weak var totalValueLbl: NSTextField!
+    
+    @IBOutlet weak var scrollView: NSScrollView!
+    @IBOutlet weak var collectionView: NSCollectionView!
+    
+    @IBOutlet weak var emptyBGView: NSView!
+    @IBOutlet weak var emptyTipImg: NSImageView!
+    @IBOutlet weak var emptyTipLbl: NSTextField!
+
+    var compareManager: KMCompareManager?
+    
+    weak var delegate: KMCompareTextViewDelegate?
+    
+    override func setup() {
+        scrollView.scrollerStyle = .overlay
+
+        collectionView.wantsLayer = true
+        collectionView.layer?.backgroundColor = NSColor.clear.cgColor
+        collectionView.delegate = self
+        collectionView.dataSource = self
+        collectionView.register(KMCompareTextViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier("KMCompareTextViewItem"))
+        collectionView.register(KMCompareTextHeaderView.self, forSupplementaryViewOfKind: NSCollectionView.elementKindSectionHeader, withIdentifier: NSUserInterfaceItemIdentifier("KMCompareTextHeaderView"))
+        collectionView.isSelectable = true
+        collectionView.allowsMultipleSelection = false
+
+        emptyBGView.isHidden = true
+    }
+    
+    override func updateLanguage() {
+        infoLbl.stringValue = NSLocalizedString("Compare", comment: "")
+        totalTitleLbl.stringValue = NSLocalizedString("Total Changes: ", comment: "")
+        emptyTipLbl.stringValue = NSLocalizedString("There is no difference between two documents.", comment: "")
+    }
+
+
+    override func reloadData() {
+        var count = 0
+        if let compareManager = compareManager {
+            for model in compareManager.compareResultModels {
+                count += Int(model.resultCounts)
+            }
+        }
+        totalValueLbl.stringValue = "\(count)"
+        if count == 0 {
+            emptyBGView.isHidden = false
+            scrollView.isHidden = true
+        } else {
+            emptyBGView.isHidden = true
+            scrollView.isHidden = false
+            collectionView.reloadData()
+        }
+    }
+
+    // MARK: - NSCollectionViewDelegate & NSCollectionViewDataSources
+
+    func numberOfSections(in collectionView: NSCollectionView) -> Int {
+        return compareManager?.compareResultModels.count ?? 0
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
+        if let model = compareManager?.compareResultModels[section], model.isExpand {
+            return Int(model.resultCounts)
+        }
+        return 0
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
+        let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier("KMCompareTextViewItem"), for: indexPath) as! KMCompareTextViewItem
+        
+        let model = compareManager!.compareResultModels[indexPath.section]
+        if indexPath.item < model.compareResults.count {
+            item.sectionIndex = indexPath.section
+            item.itemIndex = UInt(indexPath.item)
+            item.delegate = self
+            item.compareResult = model.compareResults[indexPath.item] as? CPDFCompareResult
+        }
+        return item
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, viewForSupplementaryElementOfKind kind: NSCollectionView.SupplementaryElementKind, at indexPath: IndexPath) -> NSView {
+        let view = collectionView.makeSupplementaryView(ofKind: kind, withIdentifier: NSUserInterfaceItemIdentifier("KMCompareTextHeaderView"), for: indexPath) as! KMCompareTextHeaderView
+        let model = compareManager!.compareResultModels[indexPath.section]
+        view.wantsLayer = true
+        view.layer?.backgroundColor = NSColor.clear.cgColor
+        view.delegate = self
+        view.itemIndex = indexPath.section
+        view.setUp()
+        view.resultModel = model
+        
+        return view
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
+        return NSSize(width: collectionView.frame.width, height: 32)
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> NSSize {
+        return NSSize(width: collectionView.frame.width, height: 32)
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, insetForSectionAt section: Int) -> NSEdgeInsets {
+        return NSEdgeInsetsZero
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
+        return 0.01
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
+        return 0.01
+    }
+
+    // MARK: - CPDFCompareTextItemDelegate
+    func compareTextViewItemDidClicked(_ item: KMCompareTextViewItem) {
+        collectionView.deselectAll(nil)
+
+        let indexPath = IndexPath(item: Int(item.itemIndex), section: item.sectionIndex)
+        collectionView.selectItems(at: Set([indexPath]), scrollPosition: .centeredHorizontally)
+        
+        delegate?.compareTextView(self, didSelectedResult: item.compareResult!)
+    }
+
+    // MARK: - CPDFCompareTextHeaderDelegate
+
+    func compareTextHeaderDidUpdateExpandState(_ item: KMCompareTextHeaderView) {
+        collectionView.reloadData()
+    }
+
+}

+ 190 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextView.xib

@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="243" height="476"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="PeN-Rn-SUx">
+                    <rect key="frame" x="0.0" y="0.0" width="243" height="476"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="pHd-Vz-X9j">
+                            <rect key="frame" x="0.0" y="412" width="243" height="64"/>
+                            <subviews>
+                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="Le1-KI-hRF">
+                                    <rect key="frame" x="0.0" y="24" width="243" height="40"/>
+                                    <subviews>
+                                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Pm7-yj-Q4g">
+                                            <rect key="frame" x="14" y="12" width="63" height="17"/>
+                                            <textFieldCell key="cell" lineBreakMode="clipping" title="Compare" id="aUX-Ol-yYe">
+                                                <font key="font" metaFont="system" size="14"/>
+                                                <color key="textColor" name="KMColor_Layout_H0"/>
+                                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                            </textFieldCell>
+                                        </textField>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="Pm7-yj-Q4g" firstAttribute="centerY" secondItem="Le1-KI-hRF" secondAttribute="centerY" id="3yR-FU-ncA"/>
+                                        <constraint firstAttribute="height" constant="40" id="4hu-Qx-hq0"/>
+                                        <constraint firstItem="Pm7-yj-Q4g" firstAttribute="leading" secondItem="Le1-KI-hRF" secondAttribute="leading" constant="16" id="JVj-Hz-ebU"/>
+                                    </constraints>
+                                </customView>
+                                <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="qd9-tI-ARe">
+                                    <rect key="frame" x="0.0" y="0.0" width="243" height="24"/>
+                                    <view key="contentView" id="7Bh-Tj-gbO">
+                                        <rect key="frame" x="0.0" y="0.0" width="243" height="24"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aN0-2k-pbT">
+                                                <rect key="frame" x="14" y="4" width="99" height="16"/>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Total revisions: " id="q4I-Z4-Nuo">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="KMColor_Layout_H2"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dml-eg-wPo">
+                                                <rect key="frame" x="109" y="4" width="13" height="16"/>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="0" id="tz5-QV-B0u">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="KMColor_Layout_H1"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstItem="dml-eg-wPo" firstAttribute="leading" secondItem="aN0-2k-pbT" secondAttribute="trailing" id="4vB-oQ-JOd"/>
+                                            <constraint firstItem="dml-eg-wPo" firstAttribute="centerY" secondItem="7Bh-Tj-gbO" secondAttribute="centerY" id="HHw-xx-wSL"/>
+                                            <constraint firstItem="aN0-2k-pbT" firstAttribute="centerY" secondItem="7Bh-Tj-gbO" secondAttribute="centerY" id="LXf-z8-86J"/>
+                                            <constraint firstItem="aN0-2k-pbT" firstAttribute="leading" secondItem="7Bh-Tj-gbO" secondAttribute="leading" constant="16" id="Mxp-VO-Y0o"/>
+                                        </constraints>
+                                    </view>
+                                    <color key="fillColor" name="KMColor_Layout_L_1"/>
+                                </box>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="qd9-tI-ARe" firstAttribute="leading" secondItem="pHd-Vz-X9j" secondAttribute="leading" id="Ekh-91-wAO"/>
+                                <constraint firstAttribute="bottom" secondItem="qd9-tI-ARe" secondAttribute="bottom" id="Ncv-A6-AXf"/>
+                                <constraint firstItem="Le1-KI-hRF" firstAttribute="leading" secondItem="pHd-Vz-X9j" secondAttribute="leading" id="dha-Zq-MBQ"/>
+                                <constraint firstItem="Le1-KI-hRF" firstAttribute="top" secondItem="pHd-Vz-X9j" secondAttribute="top" id="gvh-jv-jIt"/>
+                                <constraint firstAttribute="trailing" secondItem="qd9-tI-ARe" secondAttribute="trailing" id="iUQ-zj-QEu"/>
+                                <constraint firstItem="qd9-tI-ARe" firstAttribute="top" secondItem="Le1-KI-hRF" secondAttribute="bottom" id="kbv-iC-1Mq"/>
+                                <constraint firstAttribute="height" constant="64" id="xY4-zk-1N9"/>
+                                <constraint firstAttribute="trailing" secondItem="Le1-KI-hRF" secondAttribute="trailing" id="yiE-h7-dg7"/>
+                            </constraints>
+                        </customView>
+                        <scrollView wantsLayer="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WF8-6p-ltv">
+                            <rect key="frame" x="0.0" y="0.0" width="243" height="412"/>
+                            <clipView key="contentView" id="1dS-al-xOU">
+                                <rect key="frame" x="0.0" y="0.0" width="228" height="412"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                <subviews>
+                                    <collectionView id="KvW-VB-kS8">
+                                        <rect key="frame" x="0.0" y="0.0" width="228" height="463"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES"/>
+                                        <collectionViewFlowLayout key="collectionViewLayout" minimumInteritemSpacing="10" minimumLineSpacing="10" id="95L-6j-8of">
+                                            <size key="itemSize" width="50" height="50"/>
+                                        </collectionViewFlowLayout>
+                                        <color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </collectionView>
+                                </subviews>
+                            </clipView>
+                            <scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="KOI-qQ-FG6">
+                                <rect key="frame" x="-100" y="-100" width="233" height="15"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                            </scroller>
+                            <scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="3y3-8t-LQe">
+                                <rect key="frame" x="228" y="0.0" width="15" height="412"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                            </scroller>
+                        </scrollView>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="San-9F-k5E">
+                            <rect key="frame" x="0.0" y="0.0" width="243" height="412"/>
+                            <subviews>
+                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="YV3-IX-c0p">
+                                    <rect key="frame" x="14" y="192" width="216" height="176"/>
+                                    <subviews>
+                                        <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5Qj-H7-zkZ">
+                                            <rect key="frame" x="38" y="36" width="140" height="140"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="140" id="0Wj-GA-1Yk"/>
+                                                <constraint firstAttribute="height" constant="140" id="JMn-Xf-IM7"/>
+                                            </constraints>
+                                            <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="Compare_empty_icon" id="W4z-GG-oSm"/>
+                                        </imageView>
+                                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="r6w-kW-zDA">
+                                            <rect key="frame" x="14" y="0.0" width="188" height="32"/>
+                                            <textFieldCell key="cell" lineBreakMode="charWrapping" alignment="center" title="There is no difference between two documents." id="UBn-03-lUj">
+                                                <font key="font" metaFont="system"/>
+                                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                            </textFieldCell>
+                                        </textField>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="r6w-kW-zDA" firstAttribute="centerX" secondItem="YV3-IX-c0p" secondAttribute="centerX" id="Bb4-Rm-5rL"/>
+                                        <constraint firstItem="5Qj-H7-zkZ" firstAttribute="centerX" secondItem="YV3-IX-c0p" secondAttribute="centerX" id="JEe-85-WrE"/>
+                                        <constraint firstItem="r6w-kW-zDA" firstAttribute="leading" secondItem="YV3-IX-c0p" secondAttribute="leading" constant="16" id="KKj-Ap-FlV"/>
+                                        <constraint firstAttribute="width" constant="216" id="ND5-aH-HfL"/>
+                                        <constraint firstAttribute="trailing" secondItem="r6w-kW-zDA" secondAttribute="trailing" constant="16" id="sAl-HR-1no"/>
+                                        <constraint firstAttribute="bottom" secondItem="r6w-kW-zDA" secondAttribute="bottom" id="wZD-M3-5sP"/>
+                                        <constraint firstItem="5Qj-H7-zkZ" firstAttribute="top" secondItem="YV3-IX-c0p" secondAttribute="top" id="xlI-U1-sPz"/>
+                                        <constraint firstAttribute="height" constant="176" id="y2D-yD-YLf"/>
+                                    </constraints>
+                                </customView>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="YV3-IX-c0p" firstAttribute="centerY" secondItem="San-9F-k5E" secondAttribute="centerY" constant="-74" id="jeS-ME-rgc"/>
+                                <constraint firstItem="YV3-IX-c0p" firstAttribute="centerX" secondItem="San-9F-k5E" secondAttribute="centerX" id="sIT-wh-XVZ"/>
+                            </constraints>
+                        </customView>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="WF8-6p-ltv" firstAttribute="top" secondItem="PeN-Rn-SUx" secondAttribute="top" constant="64" id="4nY-ZH-HiA"/>
+                        <constraint firstAttribute="trailing" secondItem="San-9F-k5E" secondAttribute="trailing" id="99p-ld-3Hs"/>
+                        <constraint firstItem="San-9F-k5E" firstAttribute="leading" secondItem="PeN-Rn-SUx" secondAttribute="leading" id="9sz-DE-d1l"/>
+                        <constraint firstItem="San-9F-k5E" firstAttribute="top" secondItem="pHd-Vz-X9j" secondAttribute="bottom" id="Dcq-Ew-uc2"/>
+                        <constraint firstAttribute="bottom" secondItem="WF8-6p-ltv" secondAttribute="bottom" id="NXk-lP-vCX"/>
+                        <constraint firstAttribute="bottom" secondItem="San-9F-k5E" secondAttribute="bottom" id="PIr-d1-4lY"/>
+                        <constraint firstItem="WF8-6p-ltv" firstAttribute="leading" secondItem="PeN-Rn-SUx" secondAttribute="leading" id="eUU-YV-weD"/>
+                        <constraint firstAttribute="trailing" secondItem="pHd-Vz-X9j" secondAttribute="trailing" id="eiL-C9-nAl"/>
+                        <constraint firstItem="pHd-Vz-X9j" firstAttribute="top" secondItem="PeN-Rn-SUx" secondAttribute="top" id="mAm-dc-BHk"/>
+                        <constraint firstAttribute="trailing" secondItem="WF8-6p-ltv" secondAttribute="trailing" id="p9d-8S-5YW"/>
+                        <constraint firstItem="pHd-Vz-X9j" firstAttribute="leading" secondItem="PeN-Rn-SUx" secondAttribute="leading" id="pCd-b6-51m"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="PeN-Rn-SUx" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="LuD-8u-rCX"/>
+                <constraint firstAttribute="bottom" secondItem="PeN-Rn-SUx" secondAttribute="bottom" id="Rrg-mr-08F"/>
+                <constraint firstAttribute="trailing" secondItem="PeN-Rn-SUx" secondAttribute="trailing" id="amY-NX-p5j"/>
+                <constraint firstItem="PeN-Rn-SUx" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="cSs-Ja-5JJ"/>
+            </constraints>
+            <point key="canvasLocation" x="125.5" y="-135"/>
+        </customView>
+    </objects>
+    <resources>
+        <image name="Compare_empty_icon" width="140" height="140"/>
+        <namedColor name="KMColor_Layout_H0">
+            <color red="0.054901960784313725" green="0.066666666666666666" blue="0.078431372549019607" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+        <namedColor name="KMColor_Layout_H1">
+            <color red="0.25882352941176473" green="0.27450980392156865" blue="0.30196078431372547" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+        <namedColor name="KMColor_Layout_H2">
+            <color red="0.45882352941176469" green="0.46666666666666667" blue="0.50196078431372548" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+        <namedColor name="KMColor_Layout_L_1">
+            <color red="0.92156862745098034" green="0.92549019607843142" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>

+ 118 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextViewItem.swift

@@ -0,0 +1,118 @@
+//
+//  KMCompareTextViewItem.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/22.
+//
+
+protocol KMCompareTextViewItemDelegate: AnyObject {
+    func compareTextViewItemDidClicked(_ item: KMCompareTextViewItem)
+}
+
+class KMCompareTextViewItem: NSCollectionViewItem {
+
+    @IBOutlet weak var contendView: NSView!
+    @IBOutlet weak var colorView: NSView!
+    @IBOutlet weak var infoLbl: NSTextField!
+    @IBOutlet weak var indexLbl: NSTextField!
+
+    var sectionIndex: Int = 0
+    weak var delegate: KMCompareTextViewItemDelegate?
+
+    var trackingArea: NSTrackingArea?
+    var highlightColor: NSColor?
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+
+        view.wantsLayer = true
+        contendView.wantsLayer = true
+        colorView.wantsLayer = true
+        colorView.layer?.cornerRadius = 1.0
+        colorView.layer?.masksToBounds = true
+
+        highlightColor = NSColor(red: 245.0/255.0, green: 246.0/255.0, blue: 252.0/255.0, alpha: 1.0)
+        
+        // addTrackingArea()
+    }
+
+    func addTrackingArea() {
+        if trackingArea == nil {
+            trackingArea = NSTrackingArea(rect: view.bounds,
+                                          options: [.mouseEnteredAndExited, .inVisibleRect, .activeInKeyWindow],
+                                          owner: self,
+                                          userInfo: nil)
+        }
+        view.addTrackingArea(trackingArea!)
+    }
+
+    override var isSelected: Bool {
+        didSet {
+            if isSelected {
+                contendView.layer?.backgroundColor = selectedColor.cgColor
+            } else {
+                contendView.layer?.backgroundColor = NSColor.clear.cgColor
+            }
+        }
+    }
+
+    var itemIndex: UInt = 0 {
+        didSet {
+            indexLbl.stringValue = "\(itemIndex + 1)"
+        }
+    }
+
+    var compareResult: CPDFCompareResult? {
+        didSet {
+            guard let compareResult = compareResult else { return }
+
+            infoLbl.stringValue = typeStringFromResult(compareResult)
+
+            switch compareResult.type() {
+            case .delete:
+                colorView.layer?.backgroundColor = KMCompareFilesConfig.defaultConfig.deleteColor().withAlphaComponent(KMCompareFilesConfig.defaultConfig.deleteOpacity()).cgColor
+            case .insert:
+                colorView.layer?.backgroundColor = KMCompareFilesConfig.defaultConfig.insertColor().withAlphaComponent(KMCompareFilesConfig.defaultConfig.insertOpacity()).cgColor
+            case .replace, .change:
+                colorView.layer?.backgroundColor = KMCompareFilesConfig.defaultConfig.replaceColor().withAlphaComponent(KMCompareFilesConfig.defaultConfig.replaceOpacity()).cgColor
+            default:
+                break
+            }
+        }
+    }
+
+    func typeStringFromResult(_ compareResult: CPDFCompareResult) -> String {
+        if compareResult.oldBounds().equalTo(CGRect.zero) {
+            return NSLocalizedString("Insert Page", comment: "")
+        } else if compareResult.newBounds().equalTo(CGRect.zero) {
+            return NSLocalizedString("Delete Page", comment: "")
+        } else {
+            switch compareResult.type() {
+            case .delete:
+                return compareResult.isTextResult ? NSLocalizedString("Delete Text", comment: "") : NSLocalizedString("Delete Image", comment: "")
+            case .insert:
+                return compareResult.isTextResult ? NSLocalizedString("Insert Text", comment: "") : NSLocalizedString("Insert Image", comment: "")
+            case .replace:
+                return compareResult.isTextResult ? NSLocalizedString("Replace Text", comment: "") : NSLocalizedString("Replace Image", comment: "")
+            case .change:
+                return compareResult.isTextResult ? NSLocalizedString("Modify Text", comment: "") : NSLocalizedString("Modify Image", comment: "")
+            default:
+                return NSLocalizedString("None", comment: "")
+            }
+        }
+    }
+
+    var selectedColor: NSColor {
+        if KMAppearance.isDarkMode() {
+            return NSColor(red: 34/255.0, green: 122/255.0, blue: 255/255.0, alpha: 0.2)
+        } else {
+            return NSColor(red: 73/255.0, green: 130/255.0, blue: 230/255.0, alpha: 0.2)
+        }
+    }
+
+    @IBAction func buttonClicked(_ sender: Any) {
+        if let delegate = delegate {
+            delegate.compareTextViewItemDidClicked(self)
+        }
+    }
+}

+ 83 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Text/KMCompareTextViewItem.xib

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareTextViewItem" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="Hz6-mo-xeY">
+            <rect key="frame" x="0.0" y="0.0" width="319" height="48"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="e4Q-zy-R8L">
+                    <rect key="frame" x="0.0" y="0.0" width="319" height="48"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="pib-Xs-WA9">
+                            <rect key="frame" x="16" y="16" width="36" height="16"/>
+                            <subviews>
+                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="eaH-SR-06O">
+                                    <rect key="frame" x="13" y="1" width="10" height="14"/>
+                                    <textFieldCell key="cell" lineBreakMode="clipping" title="1" id="4Uz-7i-rwN">
+                                        <font key="font" metaFont="smallSystem"/>
+                                        <color key="textColor" name="Color"/>
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </textFieldCell>
+                                </textField>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="eaH-SR-06O" firstAttribute="centerX" secondItem="pib-Xs-WA9" secondAttribute="centerX" id="MaE-DW-5QX"/>
+                                <constraint firstItem="eaH-SR-06O" firstAttribute="centerY" secondItem="pib-Xs-WA9" secondAttribute="centerY" id="d3w-PU-qBI"/>
+                                <constraint firstAttribute="width" constant="36" id="g6f-KZ-4T5"/>
+                                <constraint firstAttribute="height" constant="16" id="p0x-v6-LVs"/>
+                            </constraints>
+                        </customView>
+                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NgE-PI-Vk3">
+                            <rect key="frame" x="54" y="16" width="37" height="16"/>
+                            <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="RKd-LN-vgg">
+                                <font key="font" usesAppearanceFont="YES"/>
+                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                        <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="So5-n8-9Bg">
+                            <rect key="frame" x="0.0" y="0.0" width="319" height="48"/>
+                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="siw-AQ-N3s">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="system"/>
+                            </buttonCell>
+                        </button>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="NgE-PI-Vk3" firstAttribute="leading" secondItem="pib-Xs-WA9" secondAttribute="trailing" constant="4" id="0US-MU-sLh"/>
+                        <constraint firstItem="pib-Xs-WA9" firstAttribute="centerY" secondItem="e4Q-zy-R8L" secondAttribute="centerY" id="1Xz-7C-T1q"/>
+                        <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="NgE-PI-Vk3" secondAttribute="trailing" constant="4" id="EQy-ft-1Kn"/>
+                        <constraint firstItem="NgE-PI-Vk3" firstAttribute="centerY" secondItem="e4Q-zy-R8L" secondAttribute="centerY" id="cZk-aZ-zsn"/>
+                        <constraint firstItem="pib-Xs-WA9" firstAttribute="leading" secondItem="e4Q-zy-R8L" secondAttribute="leading" constant="16" id="f14-Pd-dFD"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="e4Q-zy-R8L" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="1kO-wr-H91"/>
+                <constraint firstAttribute="trailing" secondItem="e4Q-zy-R8L" secondAttribute="trailing" id="8D8-F5-t1t"/>
+                <constraint firstAttribute="bottom" secondItem="e4Q-zy-R8L" secondAttribute="bottom" id="V0g-rl-tB6"/>
+                <constraint firstItem="e4Q-zy-R8L" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="o5c-kN-FF0"/>
+            </constraints>
+            <point key="canvasLocation" x="78" y="70"/>
+        </customView>
+    </objects>
+    <resources>
+        <namedColor name="Color">
+            <color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>

+ 124 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbItem.swift

@@ -0,0 +1,124 @@
+//
+//  KMCompareThumbItem.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/22.
+//
+
+import Cocoa
+
+protocol KMCompareThumbItemDelegate: AnyObject {
+    func compareThumbItemDidClicked(_ thumbItem: KMCompareThumbItem)
+}
+
+class KMCompareThumbItem: NSCollectionViewItem {
+
+    @IBOutlet weak var leftBGView: NSView!
+    @IBOutlet weak var leftIconImg: NSImageView!
+    @IBOutlet weak var leftIndexLbl: NSTextField!
+    
+    @IBOutlet weak var rightBGView: NSView!
+    @IBOutlet weak var rightIndexLbl: NSTextField!
+    @IBOutlet weak var rightIconImg: NSImageView!
+    
+    @IBOutlet weak var leftImgBox: NSBox!
+    @IBOutlet weak var leftLblView: NSView!
+    @IBOutlet weak var leftCoverBtn: NSButton!
+    
+    @IBOutlet weak var rightImgBox: NSBox!
+    @IBOutlet weak var rightCoverBtn: NSButton!
+    @IBOutlet weak var rightLblView: NSView!
+    
+    var compareManager: KMCompareManager?
+    var index: UInt = 0 {
+        didSet {
+            leftIndexLbl.stringValue = "\(index + 1)"
+            rightIndexLbl.stringValue = "\(index + 1)"
+            refreshStateUI()
+
+            if compareManager?.isSyncScroll ?? false {
+                if index == compareManager?.pdfSelectedIndex {
+                    leftImgBox.borderColor = KMAppearance.Interactive.a0Color()
+                    leftLblView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
+                    leftIndexLbl.textColor = NSColor.white
+
+                    rightImgBox.borderColor = KMAppearance.Interactive.a0Color()
+                    rightLblView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
+                    rightIndexLbl.textColor = NSColor.white
+                }
+            }
+        }
+    }
+    weak var delegate: KMCompareThumbItemDelegate?
+
+    func refreshStateUI() {
+        if compareManager?.isThumbItemClicked ?? false {
+            return
+        }
+
+        if compareManager?.isSelectedOldPDF ?? false {
+            if index == compareManager?.pdfSelectedIndex {
+                leftImgBox.borderColor = KMAppearance.Interactive.a0Color()
+                leftLblView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
+                leftIndexLbl.textColor = NSColor.white
+            } else {
+                leftImgBox.borderColor = KMAppearance.Layout.h2Color()
+                leftLblView.layer?.backgroundColor = NSColor.clear.cgColor
+                leftIndexLbl.textColor = KMAppearance.Layout.h0Color()
+            }
+            rightImgBox.borderColor = KMAppearance.Layout.h2Color()
+            rightLblView.layer?.backgroundColor = NSColor.clear.cgColor
+            rightIndexLbl.textColor = KMAppearance.Layout.h0Color()
+        } else {
+            if index == compareManager?.pdfSelectedIndex {
+                rightImgBox.borderColor = KMAppearance.Interactive.a0Color()
+                rightLblView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
+                rightIndexLbl.textColor = NSColor.white
+            } else {
+                rightImgBox.borderColor = KMAppearance.Layout.h2Color()
+                rightLblView.layer?.backgroundColor = NSColor.clear.cgColor
+                rightIndexLbl.textColor = KMAppearance.Layout.h0Color()
+            }
+            leftImgBox.borderColor = KMAppearance.Layout.h2Color()
+            leftLblView.layer?.backgroundColor = NSColor.clear.cgColor
+            leftIndexLbl.textColor = KMAppearance.Layout.h0Color()
+        }
+    }
+
+    @objc func selectedItemChanged(_ notification: Notification) {
+        refreshStateUI()
+    }
+
+    @IBAction func selectAction(_ sender: NSButton) {
+        if sender == leftCoverBtn {
+            compareManager?.isSelectedOldPDF = true
+            compareManager?.pdfSelectedIndex = UInt(Int(index))
+        } else if sender == rightCoverBtn {
+            compareManager?.isSelectedOldPDF = false
+            compareManager?.pdfSelectedIndex = UInt(Int(index))
+        }
+//        NotificationCenter.default.post(name: NSNotification.Name(CPDFThumbSelectChangedNoti), object: nil)
+
+        compareManager?.isThumbItemClicked = true
+        delegate?.compareThumbItemDidClicked(self)
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
+            self.compareManager?.isThumbItemClicked = false
+        }
+        
+        if compareManager?.isSyncScroll ?? false {
+            if index == compareManager?.pdfSelectedIndex {
+                leftImgBox.borderColor = KMAppearance.Interactive.a0Color()
+                leftLblView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
+                leftIndexLbl.textColor = NSColor.white
+
+                rightImgBox.borderColor = KMAppearance.Interactive.a0Color()
+                rightLblView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
+                rightIndexLbl.textColor = NSColor.white
+            }
+        }
+    }
+
+    @IBAction func itemClicked(_ sender: Any) {
+        delegate?.compareThumbItemDidClicked(self)
+    }
+}

+ 175 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbItem.xib

@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareThumbItem" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="leftBGView" destination="zyK-8a-CdZ" id="y0E-z6-SKD"/>
+                <outlet property="leftCoverBtn" destination="Ho5-nQ-kcd" id="6B3-uF-3Gd"/>
+                <outlet property="leftIconImg" destination="ucy-0r-nAv" id="yDk-LT-n0J"/>
+                <outlet property="leftImgBox" destination="ozy-SX-Pmn" id="HvI-RQ-Kff"/>
+                <outlet property="leftIndexLbl" destination="NqF-Bi-Kre" id="Y3x-wl-JLJ"/>
+                <outlet property="leftLblView" destination="QKH-pY-FXy" id="EnP-vf-QJV"/>
+                <outlet property="rightBGView" destination="HW6-PC-dbm" id="ufJ-dt-Wua"/>
+                <outlet property="rightCoverBtn" destination="3b2-9M-Kml" id="Pxi-J2-ttj"/>
+                <outlet property="rightIconImg" destination="5bo-8A-ZEv" id="7hr-Fr-MLn"/>
+                <outlet property="rightImgBox" destination="Eda-Gy-pR6" id="sIS-Ky-9DD"/>
+                <outlet property="rightIndexLbl" destination="Xyg-4d-69z" id="zac-bL-R1S"/>
+                <outlet property="rightLblView" destination="zEq-BY-UI2" id="88D-yo-a5H"/>
+                <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="Hz6-mo-xeY">
+            <rect key="frame" x="0.0" y="0.0" width="306" height="231"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="HqC-Qi-wEj">
+                    <rect key="frame" x="0.0" y="0.0" width="306" height="231"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="zyK-8a-CdZ">
+                            <rect key="frame" x="0.0" y="0.0" width="145" height="231"/>
+                            <subviews>
+                                <box boxType="custom" cornerRadius="2" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="ozy-SX-Pmn">
+                                    <rect key="frame" x="0.0" y="24" width="145" height="207"/>
+                                    <view key="contentView" id="Cb5-rZ-639">
+                                        <rect key="frame" x="1" y="1" width="143" height="205"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ucy-0r-nAv">
+                                                <rect key="frame" x="-1" y="-1" width="145" height="207"/>
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="AWm-fe-0y5"/>
+                                            </imageView>
+                                        </subviews>
+                                    </view>
+                                    <color key="borderColor" name="KMColor_Layout_H2"/>
+                                </box>
+                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="QKH-pY-FXy">
+                                    <rect key="frame" x="67" y="0.0" width="12" height="18"/>
+                                    <subviews>
+                                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NqF-Bi-Kre">
+                                            <rect key="frame" x="1" y="1" width="10" height="16"/>
+                                            <textFieldCell key="cell" lineBreakMode="clipping" title="1" id="Xt6-1a-JdY">
+                                                <font key="font" metaFont="system"/>
+                                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                            </textFieldCell>
+                                        </textField>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="NqF-Bi-Kre" firstAttribute="centerY" secondItem="QKH-pY-FXy" secondAttribute="centerY" id="RMH-Ek-9H5"/>
+                                        <constraint firstAttribute="height" constant="18" id="gW0-dX-Q5i"/>
+                                        <constraint firstAttribute="trailing" secondItem="NqF-Bi-Kre" secondAttribute="trailing" constant="3" id="lIH-fp-QhX"/>
+                                        <constraint firstItem="NqF-Bi-Kre" firstAttribute="centerX" secondItem="QKH-pY-FXy" secondAttribute="centerX" id="qR1-TE-sqq"/>
+                                        <constraint firstItem="NqF-Bi-Kre" firstAttribute="leading" secondItem="QKH-pY-FXy" secondAttribute="leading" constant="3" id="zwF-tY-nRI"/>
+                                    </constraints>
+                                </customView>
+                                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ho5-nQ-kcd">
+                                    <rect key="frame" x="0.0" y="0.0" width="145" height="231"/>
+                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                    <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="qiD-J9-tfK">
+                                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                        <font key="font" metaFont="system"/>
+                                    </buttonCell>
+                                </button>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="ozy-SX-Pmn" firstAttribute="top" secondItem="zyK-8a-CdZ" secondAttribute="top" id="7Ut-8A-kTV"/>
+                                <constraint firstAttribute="bottom" secondItem="QKH-pY-FXy" secondAttribute="bottom" id="A45-92-EpE"/>
+                                <constraint firstItem="ozy-SX-Pmn" firstAttribute="leading" secondItem="zyK-8a-CdZ" secondAttribute="leading" id="KH6-Sc-GuP"/>
+                                <constraint firstAttribute="trailing" secondItem="ozy-SX-Pmn" secondAttribute="trailing" id="W99-Kt-33A"/>
+                                <constraint firstAttribute="bottom" secondItem="ozy-SX-Pmn" secondAttribute="bottom" constant="24" id="Y6k-bn-Tv9"/>
+                                <constraint firstItem="QKH-pY-FXy" firstAttribute="centerX" secondItem="zyK-8a-CdZ" secondAttribute="centerX" id="qbb-rh-lPQ"/>
+                            </constraints>
+                        </customView>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="HW6-PC-dbm">
+                            <rect key="frame" x="161" y="0.0" width="145" height="231"/>
+                            <subviews>
+                                <box boxType="custom" cornerRadius="2" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="Eda-Gy-pR6">
+                                    <rect key="frame" x="0.0" y="24" width="145" height="207"/>
+                                    <view key="contentView" id="oYV-ur-G8k">
+                                        <rect key="frame" x="1" y="1" width="143" height="205"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5bo-8A-ZEv">
+                                                <rect key="frame" x="-1" y="-1" width="145" height="207"/>
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="HsR-ql-PQB"/>
+                                            </imageView>
+                                        </subviews>
+                                    </view>
+                                    <color key="borderColor" name="KMColor_Layout_H2"/>
+                                </box>
+                                <customView translatesAutoresizingMaskIntoConstraints="NO" id="zEq-BY-UI2">
+                                    <rect key="frame" x="67" y="0.0" width="12" height="18"/>
+                                    <subviews>
+                                        <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Xyg-4d-69z">
+                                            <rect key="frame" x="1" y="1" width="10" height="16"/>
+                                            <textFieldCell key="cell" lineBreakMode="clipping" title="1" id="i2N-9j-trn">
+                                                <font key="font" metaFont="system"/>
+                                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                            </textFieldCell>
+                                        </textField>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstAttribute="trailing" secondItem="Xyg-4d-69z" secondAttribute="trailing" constant="3" id="2Xk-Rx-G4S"/>
+                                        <constraint firstItem="Xyg-4d-69z" firstAttribute="leading" secondItem="zEq-BY-UI2" secondAttribute="leading" constant="3" id="ZvT-O1-Pvc"/>
+                                        <constraint firstAttribute="height" constant="18" id="cph-cl-UhD"/>
+                                        <constraint firstItem="Xyg-4d-69z" firstAttribute="centerY" secondItem="zEq-BY-UI2" secondAttribute="centerY" id="dWA-lo-4uo"/>
+                                        <constraint firstItem="Xyg-4d-69z" firstAttribute="centerX" secondItem="zEq-BY-UI2" secondAttribute="centerX" id="sED-w5-xyv"/>
+                                    </constraints>
+                                </customView>
+                                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3b2-9M-Kml">
+                                    <rect key="frame" x="0.0" y="0.0" width="145" height="231"/>
+                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                    <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="TTs-vk-g7b">
+                                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                        <font key="font" metaFont="system"/>
+                                    </buttonCell>
+                                </button>
+                            </subviews>
+                            <constraints>
+                                <constraint firstAttribute="bottom" secondItem="zEq-BY-UI2" secondAttribute="bottom" id="2h4-QM-gdT"/>
+                                <constraint firstAttribute="trailing" secondItem="Eda-Gy-pR6" secondAttribute="trailing" id="4g0-28-vpz"/>
+                                <constraint firstAttribute="bottom" secondItem="Eda-Gy-pR6" secondAttribute="bottom" constant="24" id="Tnn-rs-rql"/>
+                                <constraint firstItem="zEq-BY-UI2" firstAttribute="centerX" secondItem="HW6-PC-dbm" secondAttribute="centerX" id="aLq-Ea-wAw"/>
+                                <constraint firstItem="Eda-Gy-pR6" firstAttribute="top" secondItem="HW6-PC-dbm" secondAttribute="top" id="cW5-3Y-Asn"/>
+                                <constraint firstItem="Eda-Gy-pR6" firstAttribute="leading" secondItem="HW6-PC-dbm" secondAttribute="leading" id="o65-t2-ZnZ"/>
+                            </constraints>
+                        </customView>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="HW6-PC-dbm" firstAttribute="leading" secondItem="zyK-8a-CdZ" secondAttribute="trailing" constant="16" id="Db4-2N-HoB"/>
+                        <constraint firstAttribute="trailing" secondItem="HW6-PC-dbm" secondAttribute="trailing" id="MP8-hQ-VyX"/>
+                        <constraint firstItem="HW6-PC-dbm" firstAttribute="top" secondItem="HqC-Qi-wEj" secondAttribute="top" id="bAf-xO-KCA"/>
+                        <constraint firstAttribute="bottom" secondItem="zyK-8a-CdZ" secondAttribute="bottom" id="faE-24-dH1"/>
+                        <constraint firstItem="zyK-8a-CdZ" firstAttribute="width" secondItem="HqC-Qi-wEj" secondAttribute="width" multiplier="0.5" constant="-8" id="hzo-2U-30K"/>
+                        <constraint firstItem="zyK-8a-CdZ" firstAttribute="leading" secondItem="HqC-Qi-wEj" secondAttribute="leading" id="k9n-um-sBo"/>
+                        <constraint firstAttribute="bottom" secondItem="HW6-PC-dbm" secondAttribute="bottom" id="s3J-S8-RcT"/>
+                        <constraint firstItem="zyK-8a-CdZ" firstAttribute="top" secondItem="HqC-Qi-wEj" secondAttribute="top" id="zDm-H9-9pU"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="HqC-Qi-wEj" secondAttribute="bottom" id="3Xy-5C-NyC"/>
+                <constraint firstItem="HqC-Qi-wEj" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="92j-ha-LiF"/>
+                <constraint firstAttribute="trailing" secondItem="HqC-Qi-wEj" secondAttribute="trailing" id="ER6-hn-Wsk"/>
+                <constraint firstItem="HqC-Qi-wEj" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="L9W-G2-SQi"/>
+            </constraints>
+            <point key="canvasLocation" x="154" y="170.5"/>
+        </customView>
+    </objects>
+    <resources>
+        <namedColor name="KMColor_Layout_H2">
+            <color red="0.45882352941176469" green="0.46666666666666667" blue="0.50196078431372548" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>

+ 152 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbView.swift

@@ -0,0 +1,152 @@
+//
+//  KMCompareThumbView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+protocol KMCompareThumbViewDelegate: AnyObject {
+    func compareThumbViewDidItemClicked(_ controller: KMCompareThumbView)
+}
+
+class KMCompareThumbView: KMBaseXibView, NSCollectionViewDelegate, NSCollectionViewDataSource, KMCompareThumbItemDelegate {
+
+    @IBOutlet weak var contendView: NSView!
+    @IBOutlet weak var headerBGView: NSView!
+    @IBOutlet weak var infoLbl: NSTextField!
+    @IBOutlet weak var scrollView: NSScrollView!
+    @IBOutlet weak var collectionView: NSCollectionView!
+
+    weak var delegate: KMCompareThumbViewDelegate?
+    var compareManager: KMCompareManager?
+    var oldDocument: CPDFDocument?
+    var nDocument: CPDFDocument?
+
+    override func setup() {
+        contendView.wantsLayer = true
+        contendView.layer?.backgroundColor = NSColor.clear.cgColor
+
+        headerBGView.wantsLayer = true
+
+        scrollView.scrollerStyle = .overlay
+
+        collectionView.wantsLayer = true
+        // collectionView.layer?.backgroundColor = NSColor.clear.cgColor
+        collectionView.backgroundColors = [NSColor(named: "KMWhiteColorDarkChanged01")!]
+        collectionView.delegate = self
+        collectionView.dataSource = self
+        collectionView.register(KMCompareThumbItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier("KMCompareThumbItem"))
+    }
+    
+    override func updateLanguage() {
+        infoLbl.stringValue = NSLocalizedString("Thumbnails", comment: "")
+    }
+
+    // MARK: - Setter
+
+    func setCompareManager(compareManager: KMCompareManager) {
+        self.compareManager = compareManager
+    }
+
+    func setOldDocument(oldDocument: CPDFDocument) {
+        self.oldDocument = oldDocument
+    }
+
+    func setNDocument(nDocument: CPDFDocument) {
+        self.nDocument = nDocument
+    }
+
+    // MARK: - Public Methods
+
+    override func reloadData() {
+        collectionView.reloadData()
+    }
+
+    func pdfSelectionChanged() {
+        if let thumbItemClicked = self.compareManager?.isThumbItemClicked, thumbItemClicked {
+            // Handle thumb item clicked
+        } else {
+            let indexPath = Set([IndexPath(item: Int(min(compareManager?.maxPageCount ?? 0, compareManager?.pdfSelectedIndex ?? 0)), section: 0)])
+            collectionView.scrollToItems(at: indexPath, scrollPosition: .centeredVertically)
+        }
+    }
+
+    // MARK: - NSCollectionViewDelegate & NSCollectionViewDataSource
+
+    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
+        return Int(compareManager?.maxPageCount ?? 0)
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
+        let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier("KMCompareThumbItem"), for: indexPath) as! KMCompareThumbItem
+        item.compareManager = compareManager
+        item.index = UInt(indexPath.item)
+        item.delegate = self
+
+        let itemIndex = item.index
+        let pageCount = oldDocument?.pageCount ?? 0
+        if itemIndex < pageCount {
+            item.leftBGView.isHidden = false
+            DispatchQueue.global(qos: .userInitiated).async {
+                do {
+                    if let page = try self.oldDocument?.page(at: itemIndex) {
+                        let image = try page.thumbnail(of: page.size)
+                        DispatchQueue.main.async {
+                            item.leftIconImg.image = image
+                        }
+                    }
+                } catch {
+                    // Handle error
+                }
+            }
+        } else {
+            item.leftBGView.isHidden = true
+        }
+
+        let nPageCount = nDocument?.pageCount ?? 0
+        if itemIndex < nPageCount {
+            item.rightBGView.isHidden = false
+            DispatchQueue.global(qos: .userInitiated).async {
+                do {
+                    if let page = try self.nDocument?.page(at: itemIndex) {
+                        let image = try page.thumbnail(of: page.size)
+                        DispatchQueue.main.async {
+                            item.rightIconImg.image = image
+                        }
+                    }
+                } catch {
+                    // Handle error
+                }
+            }
+        } else {
+            item.rightBGView.isHidden = true
+        }
+
+        return item
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
+        return NSSize(width: 224, height: 158)
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, insetForSectionAt section: Int) -> NSEdgeInsets {
+        let offsetX = (NSWidth(contendView.frame) / 2.0) - 112
+        return NSEdgeInsets(top: 0, left: offsetX, bottom: 10, right: offsetX)
+    }
+
+    func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
+        if let indexPath = indexPaths.first, indexPath.item >= 0 {
+            // Handle item selection
+        }
+    }
+
+    // MARK: - CPDFCompareThumbItemDelegate
+
+    func compareThumbItemDidClicked(_ thumbItem: KMCompareThumbItem) {
+        if let delegate = self.delegate {
+            delegate.compareThumbViewDidItemClicked(self)
+        }
+    }
+}

+ 98 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentComplete/View/Thumb/KMCompareThumbView.xib

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareThumbController" customModule="PDF_Master" customModuleProvider="target"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="239" height="507"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="iP1-Pb-2na">
+                    <rect key="frame" x="0.0" y="0.0" width="239" height="507"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="xfL-MU-19a">
+                            <rect key="frame" x="0.0" y="467" width="239" height="40"/>
+                            <subviews>
+                                <box fixedFrame="YES" boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="wFF-zV-PpS">
+                                    <rect key="frame" x="0.0" y="0.0" width="239" height="40"/>
+                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                    <view key="contentView" id="aQI-b2-BVQ">
+                                        <rect key="frame" x="0.0" y="0.0" width="239" height="40"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                    </view>
+                                    <color key="fillColor" name="KMWhiteColorDarkChanged01"/>
+                                </box>
+                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="uCK-IF-Thq">
+                                    <rect key="frame" x="14" y="12" width="75" height="16"/>
+                                    <textFieldCell key="cell" lineBreakMode="clipping" title="Thumbnails" id="HUf-mr-Okv">
+                                        <font key="font" usesAppearanceFont="YES"/>
+                                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </textFieldCell>
+                                </textField>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="uCK-IF-Thq" firstAttribute="centerY" secondItem="xfL-MU-19a" secondAttribute="centerY" id="30n-nI-YCa"/>
+                                <constraint firstItem="uCK-IF-Thq" firstAttribute="leading" secondItem="xfL-MU-19a" secondAttribute="leading" constant="16" id="Ulw-R5-Fvj"/>
+                            </constraints>
+                        </customView>
+                        <scrollView wantsLayer="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YwO-Zv-Ep3">
+                            <rect key="frame" x="0.0" y="0.0" width="239" height="467"/>
+                            <clipView key="contentView" id="nME-ZK-dyf">
+                                <rect key="frame" x="0.0" y="0.0" width="239" height="467"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                <subviews>
+                                    <collectionView id="RTc-Jh-rmD">
+                                        <rect key="frame" x="0.0" y="0.0" width="239" height="453"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES"/>
+                                        <collectionViewFlowLayout key="collectionViewLayout" minimumInteritemSpacing="10" minimumLineSpacing="10" id="J61-9d-7Xf">
+                                            <size key="itemSize" width="50" height="50"/>
+                                        </collectionViewFlowLayout>
+                                        <color key="primaryBackgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                    </collectionView>
+                                </subviews>
+                            </clipView>
+                            <scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="Y6Z-ZB-NaI">
+                                <rect key="frame" x="-100" y="-100" width="233" height="15"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                            </scroller>
+                            <scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="j9D-5r-OeB">
+                                <rect key="frame" x="304" y="0.0" width="15" height="447"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                            </scroller>
+                        </scrollView>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="YwO-Zv-Ep3" firstAttribute="top" secondItem="xfL-MU-19a" secondAttribute="bottom" id="3zq-az-3sa"/>
+                        <constraint firstAttribute="trailing" secondItem="YwO-Zv-Ep3" secondAttribute="trailing" id="BJD-dr-NGf"/>
+                        <constraint firstAttribute="trailing" secondItem="xfL-MU-19a" secondAttribute="trailing" id="GNz-oN-LGr"/>
+                        <constraint firstItem="xfL-MU-19a" firstAttribute="leading" secondItem="iP1-Pb-2na" secondAttribute="leading" id="Hvc-8O-La1"/>
+                        <constraint firstItem="YwO-Zv-Ep3" firstAttribute="top" secondItem="iP1-Pb-2na" secondAttribute="top" constant="40" id="Kce-HL-4mo"/>
+                        <constraint firstItem="xfL-MU-19a" firstAttribute="top" secondItem="iP1-Pb-2na" secondAttribute="top" id="Tun-rg-6Nz"/>
+                        <constraint firstItem="YwO-Zv-Ep3" firstAttribute="leading" secondItem="iP1-Pb-2na" secondAttribute="leading" id="im3-sM-xy0"/>
+                        <constraint firstAttribute="bottom" secondItem="YwO-Zv-Ep3" secondAttribute="bottom" id="lpU-24-Kaa"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="iP1-Pb-2na" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="QAv-Ok-NWk"/>
+                <constraint firstItem="iP1-Pb-2na" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="VUR-ti-oOR"/>
+                <constraint firstAttribute="trailing" secondItem="iP1-Pb-2na" secondAttribute="trailing" id="fBS-ct-NTT"/>
+                <constraint firstAttribute="bottom" secondItem="iP1-Pb-2na" secondAttribute="bottom" id="fQV-J5-Nhg"/>
+            </constraints>
+            <point key="canvasLocation" x="46.5" y="43.5"/>
+        </customView>
+    </objects>
+    <resources>
+        <namedColor name="KMWhiteColorDarkChanged01">
+            <color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>

+ 20 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/KMCompareContentSettingWindowController.swift

@@ -0,0 +1,20 @@
+//
+//  KMCompareContentSettingWindowController.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareContentSettingWindowController: NSWindowController {
+
+    @IBOutlet weak var settingView: KMCompareContentSettingView!
+    override func windowDidLoad() {
+        super.windowDidLoad()
+
+        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
+        window?.title = NSLocalizedString("Settings", comment: "")
+    }
+    
+}

+ 45 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/KMCompareContentSettingWindowController.xib

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareContentSettingWindowController" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="settingView" destination="5Qu-Wa-gxe" id="5o1-KH-Hyj"/>
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+            <rect key="contentRect" x="196" y="240" width="296" height="112"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
+            <value key="minSize" type="size" width="296" height="112"/>
+            <value key="maxSize" type="size" width="296" height="112"/>
+            <view key="contentView" id="se5-gp-TjO">
+                <rect key="frame" x="0.0" y="0.0" width="296" height="112"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="5Qu-Wa-gxe" customClass="KMCompareContentSettingView" customModule="PDF_Master" customModuleProvider="target">
+                        <rect key="frame" x="0.0" y="0.0" width="296" height="112"/>
+                    </customView>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="5Qu-Wa-gxe" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" id="mYx-ef-A6j"/>
+                    <constraint firstAttribute="bottom" secondItem="5Qu-Wa-gxe" secondAttribute="bottom" id="ns9-iM-RYH"/>
+                    <constraint firstItem="5Qu-Wa-gxe" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" id="sdx-Tp-ro4"/>
+                    <constraint firstAttribute="trailing" secondItem="5Qu-Wa-gxe" secondAttribute="trailing" id="y7M-VX-l3O"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
+            </connections>
+            <point key="canvasLocation" x="227" y="134.5"/>
+        </window>
+    </objects>
+</document>

+ 78 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/View/KMCompareContentSettingView.swift

@@ -0,0 +1,78 @@
+//
+//  KMCompareContentSettingView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareContentSettingView: KMBaseXibView {
+    @IBOutlet var replaceLabel: NSTextField!
+    @IBOutlet var insertLabel: NSTextField!
+    @IBOutlet var deleteLabel: NSTextField!
+    
+    @IBOutlet var replaceWell: NSColorWell!
+    @IBOutlet var insertWell: NSColorWell!
+    @IBOutlet var deleteWell: NSColorWell!
+    
+    
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+    }
+    
+    override func setup() {
+        
+    }
+    
+    override func updateLanguage() {
+        replaceLabel.stringValue = NSLocalizedString("Replace Color", comment: "")
+        insertLabel.stringValue = NSLocalizedString("Insert Color", comment: "")
+        deleteLabel.stringValue = NSLocalizedString("Delete Color", comment: "")
+    }
+    
+    override func reloadData() {
+        let config = KMCompareFilesConfig.defaultConfig
+        
+        var insertColor = config.insertColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        insertColor = insertColor?.withAlphaComponent(config.insertOpacity())
+        
+        var deleteColor = config.deleteColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        deleteColor = deleteColor?.withAlphaComponent(config.deleteOpacity())
+        
+        var replaceColor = config.replaceColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        replaceColor = replaceColor?.withAlphaComponent(config.replaceOpacity())
+        
+        insertWell.color = insertColor!
+        deleteWell.color = deleteColor!
+        replaceWell.color = replaceColor!
+    }
+    
+    @IBAction func replaceColorWellChanged(_ sender: NSColorWell) {
+        if let color = sender.color.usingColorSpaceName(NSColorSpaceName.calibratedRGB) {
+            let config = KMCompareFilesConfig.defaultConfig
+            config.setReplaceColor(color)
+            config.setReplaceOpacity(color.alphaComponent)
+        }
+    }
+    
+    @IBAction func deleteColorWellChanged(_ sender: NSColorWell) {
+        if let color = sender.color.usingColorSpaceName(NSColorSpaceName.calibratedRGB) {
+            let config = KMCompareFilesConfig.defaultConfig
+            config.setDeleteColor(color)
+            config.setDeleteOpacity(color.alphaComponent)
+        }
+    }
+    
+    @IBAction func insertColorWellChanged(_ sender: NSColorWell) {
+        if let color = sender.color.usingColorSpaceName(NSColorSpaceName.calibratedRGB) {
+            let config = KMCompareFilesConfig.defaultConfig
+            config.setInsertColor(color)
+            config.setInsertOpacity(color.alphaComponent)
+        }
+    }
+    
+    @IBAction func dismissSheet(_ sender: Any) {
+        self.window?.close()
+    }
+}

+ 120 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/ContentSetting/View/KMCompareContentSettingView.xib

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareContentSettingView" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="deleteLabel" destination="h2q-Hr-Hjt" id="iq8-cr-LvF"/>
+                <outlet property="deleteWell" destination="US0-Hl-kCs" id="HYY-gc-XZq"/>
+                <outlet property="insertLabel" destination="Q5d-e5-Voi" id="wVL-Qv-I4j"/>
+                <outlet property="insertWell" destination="HB7-2f-4HF" id="1Tp-9J-AYv"/>
+                <outlet property="replaceLabel" destination="Rox-St-jHi" id="5QP-dK-dHO"/>
+                <outlet property="replaceWell" destination="EhU-OV-qNQ" id="Gja-Hn-vH4"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="296" height="112"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <view translatesAutoresizingMaskIntoConstraints="NO" id="yYz-Iw-kvl">
+                    <rect key="frame" x="0.0" y="0.0" width="296" height="112"/>
+                    <subviews>
+                        <box fixedFrame="YES" boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="1gu-LE-5W9">
+                            <rect key="frame" x="0.0" y="0.0" width="296" height="112"/>
+                            <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
+                            <view key="contentView" id="KzP-qa-dRL">
+                                <rect key="frame" x="0.0" y="0.0" width="296" height="112"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                <subviews>
+                                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="49h-yx-yXf">
+                                        <rect key="frame" x="20" y="16" width="256" height="80"/>
+                                        <subviews>
+                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Rox-St-jHi">
+                                                <rect key="frame" x="13" y="60" width="132" height="16"/>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Remplacer la couleur" id="GRw-yu-djk">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <colorWell translatesAutoresizingMaskIntoConstraints="NO" id="EhU-OV-qNQ">
+                                                <rect key="frame" x="155" y="54" width="44" height="28"/>
+                                                <color key="color" red="0.05813049898" green="0.055541899059999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                                <connections>
+                                                    <action selector="replaceColorWellChanged:" target="-2" id="4q8-lG-Qb9"/>
+                                                </connections>
+                                            </colorWell>
+                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Q5d-e5-Voi">
+                                                <rect key="frame" x="13" y="32" width="75" height="16"/>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Insert Color" id="D9B-aP-Efb">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <colorWell translatesAutoresizingMaskIntoConstraints="NO" id="HB7-2f-4HF">
+                                                <rect key="frame" x="155" y="26" width="44" height="28"/>
+                                                <color key="color" red="0.05813049898" green="0.055541899059999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                                <connections>
+                                                    <action selector="deleteColorWellChanged:" target="-2" id="CGE-HO-qvH"/>
+                                                </connections>
+                                            </colorWell>
+                                            <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="h2q-Hr-Hjt">
+                                                <rect key="frame" x="13" y="4" width="80" height="16"/>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Delete Color" id="eu4-it-bGe">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <colorWell translatesAutoresizingMaskIntoConstraints="NO" id="US0-Hl-kCs">
+                                                <rect key="frame" x="155" y="-2" width="44" height="28"/>
+                                                <color key="color" red="0.05813049898" green="0.055541899059999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                                <connections>
+                                                    <action selector="insertColorWellChanged:" target="-2" id="4gT-BV-jha"/>
+                                                </connections>
+                                            </colorWell>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstAttribute="width" constant="256" id="1qA-PQ-a0B"/>
+                                            <constraint firstItem="EhU-OV-qNQ" firstAttribute="leading" secondItem="Rox-St-jHi" secondAttribute="trailing" constant="15" id="30F-2q-XZE"/>
+                                            <constraint firstItem="US0-Hl-kCs" firstAttribute="centerY" secondItem="h2q-Hr-Hjt" secondAttribute="centerY" id="4NB-Vr-iSG"/>
+                                            <constraint firstItem="Rox-St-jHi" firstAttribute="top" secondItem="49h-yx-yXf" secondAttribute="top" constant="4" id="ESn-nq-uAZ"/>
+                                            <constraint firstItem="Q5d-e5-Voi" firstAttribute="top" secondItem="Rox-St-jHi" secondAttribute="bottom" constant="12" id="Kht-cI-v5R"/>
+                                            <constraint firstItem="h2q-Hr-Hjt" firstAttribute="leading" secondItem="49h-yx-yXf" secondAttribute="leading" constant="15" id="LRl-RX-gah"/>
+                                            <constraint firstItem="Rox-St-jHi" firstAttribute="leading" secondItem="49h-yx-yXf" secondAttribute="leading" constant="15" id="VfQ-8U-vMw"/>
+                                            <constraint firstItem="h2q-Hr-Hjt" firstAttribute="top" secondItem="Q5d-e5-Voi" secondAttribute="bottom" constant="12" id="ZMS-CQ-gbB"/>
+                                            <constraint firstItem="HB7-2f-4HF" firstAttribute="leading" secondItem="US0-Hl-kCs" secondAttribute="leading" id="hED-Gp-vNe"/>
+                                            <constraint firstItem="EhU-OV-qNQ" firstAttribute="leading" secondItem="HB7-2f-4HF" secondAttribute="leading" id="l10-5H-yNl"/>
+                                            <constraint firstItem="HB7-2f-4HF" firstAttribute="centerY" secondItem="Q5d-e5-Voi" secondAttribute="centerY" id="v34-BC-Siu"/>
+                                            <constraint firstItem="Q5d-e5-Voi" firstAttribute="leading" secondItem="49h-yx-yXf" secondAttribute="leading" constant="15" id="yFo-rf-l9L"/>
+                                            <constraint firstItem="EhU-OV-qNQ" firstAttribute="centerY" secondItem="Rox-St-jHi" secondAttribute="centerY" id="yI4-ry-36e"/>
+                                            <constraint firstAttribute="height" constant="80" id="zX5-DJ-JwF"/>
+                                        </constraints>
+                                    </customView>
+                                </subviews>
+                                <constraints>
+                                    <constraint firstItem="49h-yx-yXf" firstAttribute="centerY" secondItem="KzP-qa-dRL" secondAttribute="centerY" id="68H-2a-5bG"/>
+                                    <constraint firstItem="49h-yx-yXf" firstAttribute="centerX" secondItem="KzP-qa-dRL" secondAttribute="centerX" id="9Ss-xv-lIK"/>
+                                </constraints>
+                            </view>
+                        </box>
+                    </subviews>
+                </view>
+            </subviews>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="yYz-Iw-kvl" secondAttribute="trailing" id="57K-gJ-VoJ"/>
+                <constraint firstAttribute="bottom" secondItem="yYz-Iw-kvl" secondAttribute="bottom" id="Ci9-p8-DBK"/>
+                <constraint firstItem="yYz-Iw-kvl" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="ECI-I6-0RK"/>
+                <constraint firstItem="yYz-Iw-kvl" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="Rh9-hW-fxM"/>
+            </constraints>
+            <point key="canvasLocation" x="182" y="149"/>
+        </customView>
+    </objects>
+</document>

+ 31 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/KMCompareCoveringWindowController.swift

@@ -0,0 +1,31 @@
+//
+//  KMCompareCoveringWindowController.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareCoveringWindowController: NSWindowController {
+
+    @IBOutlet weak var coveringView: KMCompareCoveringView!
+    var pdfDocument: CPDFDocument?
+    
+    var hideCloseInfo: Bool = false
+    
+    var saveHandle: ((KMCompareCoveringWindowController) -> Void)?
+    var closeHandle: ((KMCompareCoveringWindowController) -> Void)?
+    
+    convenience init(document: CPDFDocument) {
+        self.init(windowNibName: "KMCompareCoveringWindowController")
+        self.pdfDocument = document
+    }
+    
+    override func windowDidLoad() {
+        super.windowDidLoad()
+
+        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
+    }
+    
+}

+ 43 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/KMCompareCoveringWindowController.xib

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareCoveringWindowController" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="coveringView" destination="B9i-XN-eIE" id="BOH-gn-GCz"/>
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="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="2560" height="1415"/>
+            <view key="contentView" id="se5-gp-TjO">
+                <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="B9i-XN-eIE" customClass="KMCompareCoveringView" customModule="PDF_Master" customModuleProvider="target">
+                        <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
+                    </customView>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="B9i-XN-eIE" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" id="0kg-0i-lgX"/>
+                    <constraint firstAttribute="bottom" secondItem="B9i-XN-eIE" secondAttribute="bottom" id="aAF-eu-aYe"/>
+                    <constraint firstItem="B9i-XN-eIE" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" id="aiv-CL-Oqo"/>
+                    <constraint firstAttribute="trailing" secondItem="B9i-XN-eIE" secondAttribute="trailing" id="ic2-wm-9Pp"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
+            </connections>
+            <point key="canvasLocation" x="-27" y="114"/>
+        </window>
+    </objects>
+</document>

+ 80 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/View/KMCompareCoveringView.swift

@@ -0,0 +1,80 @@
+//
+//  KMCompareCoveringView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareCoveringView: KMBaseXibView {
+    
+    @IBOutlet weak var contendView: NSView!
+    @IBOutlet weak var topToolbarBox: NSBox!
+    
+    @IBOutlet weak var oldPBGView: NSView!
+    @IBOutlet weak var oldPColorView: NSView!
+    @IBOutlet weak var oldPLbl: NSTextField!
+    
+    @IBOutlet weak var nPDFBGView: NSView!
+    @IBOutlet weak var nPDFColorView: NSView!
+    @IBOutlet weak var nPDFLbl: NSTextField!
+    
+    @IBOutlet weak var saveBtn: NSButton!
+    
+    @IBOutlet weak var closeBox: NSBox!
+    @IBOutlet weak var closeBtn: NSButton!
+    
+    @IBOutlet weak var pdfView: CPDFView!
+    
+    private var pdfDocument: CPDFDocument? {
+        didSet {
+            pdfView.document = pdfDocument
+        }
+    }
+
+    var hideCloseInfo: Bool = false {
+        didSet {
+            closeBox.isHidden = hideCloseInfo
+        }
+    }
+    
+    var saveHandle: ((KMCompareCoveringView) -> Void)?
+    var closeHandle: ((KMCompareCoveringView) -> Void)?
+    
+
+    override func setup() {
+        oldPColorView.wantsLayer = true
+        nPDFColorView.wantsLayer = true
+        oldPColorView.layer?.cornerRadius = 4
+        nPDFColorView.layer?.cornerRadius = 4
+        oldPColorView.layer?.masksToBounds = true
+        nPDFColorView.layer?.masksToBounds = true
+        oldPColorView.layer?.backgroundColor = KMCompareFilesConfig.defaultConfig.oldStrokeColor().cgColor
+        nPDFColorView.layer?.backgroundColor = KMCompareFilesConfig.defaultConfig.newStrokeColor().cgColor
+        
+        saveBtn.setTitleColor(NSColor.white)
+        closeBtn.setTitleColor(NSColor.white)
+    }
+
+    override func reloadData() {
+        pdfView.document = pdfDocument
+    }
+    
+    override func updateLanguage() {
+        oldPLbl.stringValue = NSLocalizedString("Old Document", comment: "")
+        nPDFLbl.stringValue = NSLocalizedString("New Document", comment: "")
+        
+        saveBtn.title = NSLocalizedString("Save", comment: "")
+        closeBtn.title = NSLocalizedString("Close", comment: "")
+    }
+    // MARK: - IBAction
+
+    @IBAction func saveAction(_ sender: NSButton) {
+        saveHandle?(self)
+    }
+
+    @IBAction func closeAction(_ sender: NSButton) {
+        closeHandle?(self)
+    }
+}

+ 215 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringComplete/View/KMCompareCoveringView.xib

@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareCoveringView" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="closeBox" destination="Avr-no-iLV" id="Atb-7u-YVn"/>
+                <outlet property="closeBtn" destination="VmC-dF-730" id="Faj-s1-kDi"/>
+                <outlet property="contendView" destination="9S9-OJ-rer" id="MTt-LN-iBE"/>
+                <outlet property="nPDFBGView" destination="xw3-4B-iTy" id="E5d-MB-fFO"/>
+                <outlet property="nPDFColorView" destination="fU2-tY-UlJ" id="CPO-0E-pOu"/>
+                <outlet property="nPDFLbl" destination="xw3-4B-iTy" id="2Hl-oq-jZJ"/>
+                <outlet property="oldPBGView" destination="HYe-su-ZGt" id="SCy-eI-QOt"/>
+                <outlet property="oldPColorView" destination="hO1-XE-J2T" id="hs5-e6-sWF"/>
+                <outlet property="oldPLbl" destination="HYe-su-ZGt" id="Asc-4l-1TM"/>
+                <outlet property="pdfView" destination="xjc-R5-aol" id="vYa-89-piu"/>
+                <outlet property="saveBtn" destination="Hae-D8-tGZ" id="b0o-gB-d6h"/>
+                <outlet property="topToolbarBox" destination="zfO-rE-4cX" id="2uP-sL-Nik"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="582" height="352"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="9S9-OJ-rer">
+                    <rect key="frame" x="0.0" y="0.0" width="582" height="352"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="WZd-Uf-wDR">
+                            <rect key="frame" x="0.0" y="312" width="582" height="40"/>
+                            <subviews>
+                                <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="zfO-rE-4cX">
+                                    <rect key="frame" x="0.0" y="0.0" width="582" height="40"/>
+                                    <view key="contentView" id="AWJ-o3-CKg">
+                                        <rect key="frame" x="0.0" y="0.0" width="582" height="40"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="jX8-Re-s89">
+                                                <rect key="frame" x="16" y="12" width="108" height="16"/>
+                                                <subviews>
+                                                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="hO1-XE-J2T">
+                                                        <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="width" constant="16" id="kSN-FC-tcd"/>
+                                                            <constraint firstAttribute="height" constant="16" id="m9h-UQ-uyU"/>
+                                                        </constraints>
+                                                    </customView>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="HYe-su-ZGt">
+                                                        <rect key="frame" x="22" y="1" width="86" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="clipping" title="Old Document" id="8E3-Gj-FNc">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstItem="HYe-su-ZGt" firstAttribute="leading" secondItem="hO1-XE-J2T" secondAttribute="trailing" constant="8" id="1Xh-9g-J7m"/>
+                                                    <constraint firstItem="HYe-su-ZGt" firstAttribute="centerY" secondItem="jX8-Re-s89" secondAttribute="centerY" id="2Da-x5-x5e"/>
+                                                    <constraint firstItem="hO1-XE-J2T" firstAttribute="top" secondItem="jX8-Re-s89" secondAttribute="top" id="Ans-xk-9Rc"/>
+                                                    <constraint firstItem="hO1-XE-J2T" firstAttribute="leading" secondItem="jX8-Re-s89" secondAttribute="leading" id="e6P-fE-72Z"/>
+                                                    <constraint firstAttribute="height" constant="16" id="jsF-pU-tJQ"/>
+                                                    <constraint firstAttribute="trailing" secondItem="HYe-su-ZGt" secondAttribute="trailing" constant="2" id="vYC-5I-vJ7"/>
+                                                </constraints>
+                                            </customView>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="g4U-Yq-fYR">
+                                                <rect key="frame" x="150" y="12" width="113" height="16"/>
+                                                <subviews>
+                                                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="fU2-tY-UlJ">
+                                                        <rect key="frame" x="0.0" y="0.0" width="16" height="16"/>
+                                                        <constraints>
+                                                            <constraint firstAttribute="height" constant="16" id="gny-Hi-Sxv"/>
+                                                            <constraint firstAttribute="width" constant="16" id="q2r-j5-eIe"/>
+                                                        </constraints>
+                                                    </customView>
+                                                    <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xw3-4B-iTy">
+                                                        <rect key="frame" x="22" y="1" width="91" height="15"/>
+                                                        <textFieldCell key="cell" lineBreakMode="clipping" title="New Document" id="MID-O3-eTW">
+                                                            <font key="font" metaFont="cellTitle"/>
+                                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                </subviews>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="6aL-Oh-e9O"/>
+                                                    <constraint firstItem="fU2-tY-UlJ" firstAttribute="leading" secondItem="g4U-Yq-fYR" secondAttribute="leading" id="7p2-Zq-cMh"/>
+                                                    <constraint firstAttribute="trailing" secondItem="xw3-4B-iTy" secondAttribute="trailing" constant="2" id="BfG-k7-VyV"/>
+                                                    <constraint firstItem="xw3-4B-iTy" firstAttribute="leading" secondItem="fU2-tY-UlJ" secondAttribute="trailing" constant="8" id="Fty-cY-I8B"/>
+                                                    <constraint firstItem="xw3-4B-iTy" firstAttribute="centerY" secondItem="g4U-Yq-fYR" secondAttribute="centerY" id="O2d-FW-tv6"/>
+                                                    <constraint firstItem="fU2-tY-UlJ" firstAttribute="top" secondItem="g4U-Yq-fYR" secondAttribute="top" id="vhA-ee-cZt"/>
+                                                </constraints>
+                                            </customView>
+                                            <box boxType="custom" borderWidth="0.0" cornerRadius="2" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="7Ap-zz-ycF">
+                                                <rect key="frame" x="492" y="7" width="74" height="26"/>
+                                                <view key="contentView" id="tlO-5d-tlG">
+                                                    <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                    <subviews>
+                                                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Hae-D8-tGZ">
+                                                            <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                            <buttonCell key="cell" type="bevel" title="Save" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="MQg-d7-QGm">
+                                                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                                <font key="font" metaFont="system"/>
+                                                            </buttonCell>
+                                                            <connections>
+                                                                <action selector="saveAction:" target="-2" id="2d9-wv-7Xk"/>
+                                                            </connections>
+                                                        </button>
+                                                    </subviews>
+                                                    <constraints>
+                                                        <constraint firstAttribute="bottom" secondItem="Hae-D8-tGZ" secondAttribute="bottom" id="KA1-V4-4bT"/>
+                                                        <constraint firstItem="Hae-D8-tGZ" firstAttribute="top" secondItem="tlO-5d-tlG" secondAttribute="top" id="Ny3-si-asF"/>
+                                                        <constraint firstItem="Hae-D8-tGZ" firstAttribute="leading" secondItem="tlO-5d-tlG" secondAttribute="leading" id="V9u-1f-1ev"/>
+                                                        <constraint firstAttribute="trailing" secondItem="Hae-D8-tGZ" secondAttribute="trailing" id="occ-5q-e3N"/>
+                                                    </constraints>
+                                                </view>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="74" id="09k-w4-1UK"/>
+                                                    <constraint firstAttribute="height" constant="26" id="9gW-8p-t4e"/>
+                                                </constraints>
+                                                <color key="fillColor" name="KMColor_Interactive_A0"/>
+                                            </box>
+                                            <box boxType="custom" borderWidth="0.0" cornerRadius="2" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="Avr-no-iLV">
+                                                <rect key="frame" x="402" y="7" width="74" height="26"/>
+                                                <view key="contentView" id="W75-Ux-4WL">
+                                                    <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                    <subviews>
+                                                        <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VmC-dF-730">
+                                                            <rect key="frame" x="0.0" y="0.0" width="74" height="26"/>
+                                                            <buttonCell key="cell" type="bevel" title="Close" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="Vy1-ni-ipw">
+                                                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                                <font key="font" metaFont="system"/>
+                                                            </buttonCell>
+                                                            <connections>
+                                                                <action selector="closeAction:" target="-2" id="etQ-LG-pHy"/>
+                                                            </connections>
+                                                        </button>
+                                                    </subviews>
+                                                    <constraints>
+                                                        <constraint firstAttribute="trailing" secondItem="VmC-dF-730" secondAttribute="trailing" id="7Ze-hr-O2p"/>
+                                                        <constraint firstAttribute="bottom" secondItem="VmC-dF-730" secondAttribute="bottom" id="Vhz-kE-AuB"/>
+                                                        <constraint firstItem="VmC-dF-730" firstAttribute="leading" secondItem="W75-Ux-4WL" secondAttribute="leading" id="nVK-hN-LKf"/>
+                                                        <constraint firstItem="VmC-dF-730" firstAttribute="top" secondItem="W75-Ux-4WL" secondAttribute="top" id="zIu-DF-Zh2"/>
+                                                    </constraints>
+                                                </view>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="74" id="V48-0C-TL6"/>
+                                                    <constraint firstAttribute="height" constant="26" id="lq4-Yl-G9O"/>
+                                                </constraints>
+                                                <color key="fillColor" name="KMColor_Interactive_A0"/>
+                                            </box>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstItem="7Ap-zz-ycF" firstAttribute="centerY" secondItem="AWJ-o3-CKg" secondAttribute="centerY" id="3eG-Ne-1sB"/>
+                                            <constraint firstItem="g4U-Yq-fYR" firstAttribute="leading" secondItem="jX8-Re-s89" secondAttribute="trailing" constant="26" id="Dug-dD-8MH"/>
+                                            <constraint firstItem="g4U-Yq-fYR" firstAttribute="centerY" secondItem="AWJ-o3-CKg" secondAttribute="centerY" id="GrJ-kp-HJ8"/>
+                                            <constraint firstItem="Avr-no-iLV" firstAttribute="centerY" secondItem="AWJ-o3-CKg" secondAttribute="centerY" id="N8X-RA-Z66"/>
+                                            <constraint firstAttribute="trailing" secondItem="7Ap-zz-ycF" secondAttribute="trailing" constant="16" id="Van-Kn-pCY"/>
+                                            <constraint firstItem="jX8-Re-s89" firstAttribute="centerY" secondItem="AWJ-o3-CKg" secondAttribute="centerY" id="We1-rV-LgY"/>
+                                            <constraint firstItem="jX8-Re-s89" firstAttribute="leading" secondItem="AWJ-o3-CKg" secondAttribute="leading" constant="16" id="b0U-wn-AAH"/>
+                                            <constraint firstItem="7Ap-zz-ycF" firstAttribute="leading" secondItem="Avr-no-iLV" secondAttribute="trailing" constant="16" id="dk2-Md-baM"/>
+                                        </constraints>
+                                    </view>
+                                    <color key="fillColor" name="KMColor_Layout_L0"/>
+                                </box>
+                            </subviews>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="40" id="4Lj-yZ-OK9"/>
+                                <constraint firstAttribute="bottom" secondItem="zfO-rE-4cX" secondAttribute="bottom" id="bI4-dH-nHk"/>
+                                <constraint firstAttribute="trailing" secondItem="zfO-rE-4cX" secondAttribute="trailing" id="bU1-4l-di9"/>
+                                <constraint firstItem="zfO-rE-4cX" firstAttribute="top" secondItem="WZd-Uf-wDR" secondAttribute="top" id="iHu-NT-WlW"/>
+                                <constraint firstItem="zfO-rE-4cX" firstAttribute="leading" secondItem="WZd-Uf-wDR" secondAttribute="leading" id="s2I-Ta-17H"/>
+                            </constraints>
+                        </customView>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="xjc-R5-aol" customClass="CPDFView">
+                            <rect key="frame" x="0.0" y="0.0" width="582" height="312"/>
+                        </customView>
+                    </subviews>
+                    <constraints>
+                        <constraint firstAttribute="trailing" secondItem="WZd-Uf-wDR" secondAttribute="trailing" id="056-rx-OJ8"/>
+                        <constraint firstItem="xjc-R5-aol" firstAttribute="top" secondItem="WZd-Uf-wDR" secondAttribute="bottom" id="7f7-Ou-mSo"/>
+                        <constraint firstItem="WZd-Uf-wDR" firstAttribute="leading" secondItem="9S9-OJ-rer" secondAttribute="leading" id="9ru-rT-hmr"/>
+                        <constraint firstAttribute="trailing" secondItem="xjc-R5-aol" secondAttribute="trailing" id="Ah2-5a-Omu"/>
+                        <constraint firstItem="WZd-Uf-wDR" firstAttribute="top" secondItem="9S9-OJ-rer" secondAttribute="top" id="YSk-Ik-ec5"/>
+                        <constraint firstItem="xjc-R5-aol" firstAttribute="leading" secondItem="9S9-OJ-rer" secondAttribute="leading" id="YzI-Ms-IMA"/>
+                        <constraint firstAttribute="bottom" secondItem="xjc-R5-aol" secondAttribute="bottom" id="cCY-YC-QdC"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="9S9-OJ-rer" secondAttribute="trailing" id="46S-z0-OgS"/>
+                <constraint firstItem="9S9-OJ-rer" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="Gj4-hd-xAi"/>
+                <constraint firstAttribute="bottom" secondItem="9S9-OJ-rer" secondAttribute="bottom" id="HI4-aA-FXv"/>
+                <constraint firstItem="9S9-OJ-rer" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="q90-07-76t"/>
+            </constraints>
+            <point key="canvasLocation" x="190" y="156"/>
+        </customView>
+    </objects>
+    <resources>
+        <namedColor name="KMColor_Interactive_A0">
+            <color red="0.28627450980392155" green="0.50980392156862742" blue="0.90196078431372551" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+        <namedColor name="KMColor_Layout_L0">
+            <color red="0.9882352941176471" green="0.99215686274509807" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>

+ 21 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/KMCompareCoveringSettingWindowController.swift

@@ -0,0 +1,21 @@
+//
+//  KMCompareCoveringSettingWindowController.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareCoveringSettingWindowController: NSWindowController {
+
+    @IBOutlet weak var settingView: KMCompareCoveringSettingView!
+    override func windowDidLoad() {
+        super.windowDidLoad()
+
+        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
+        
+        window?.title = NSLocalizedString("Settings", comment: "")
+    }
+    
+}

+ 45 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/KMCompareCoveringSettingWindowController.xib

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareCoveringSettingWindowController" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="settingView" destination="2wq-YT-yoc" id="Iw4-fj-j1D"/>
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+            <rect key="contentRect" x="196" y="240" width="366" height="269"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
+            <value key="minSize" type="size" width="366" height="269"/>
+            <value key="maxSize" type="size" width="366" height="269"/>
+            <view key="contentView" id="se5-gp-TjO">
+                <rect key="frame" x="0.0" y="0.0" width="366" height="269"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="2wq-YT-yoc" customClass="KMCompareCoveringSettingView" customModule="PDF_Master" customModuleProvider="target">
+                        <rect key="frame" x="0.0" y="0.0" width="366" height="269"/>
+                    </customView>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="trailing" secondItem="2wq-YT-yoc" secondAttribute="trailing" id="BK5-dh-Fvl"/>
+                    <constraint firstItem="2wq-YT-yoc" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" id="ZKY-oU-nup"/>
+                    <constraint firstItem="2wq-YT-yoc" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" id="kAY-Lg-qjW"/>
+                    <constraint firstAttribute="bottom" secondItem="2wq-YT-yoc" secondAttribute="bottom" id="p3n-FR-gCI"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
+            </connections>
+            <point key="canvasLocation" x="194" y="-148"/>
+        </window>
+    </objects>
+</document>

+ 212 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/View/KMCompareCoveringSettingView.swift

@@ -0,0 +1,212 @@
+//
+//  KMCompareCoveringSettingView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/20.
+//
+
+import Cocoa
+
+class KMCompareCoveringSettingView: KMBaseXibView {
+    @IBOutlet var coveringCompareBox: NSBox!
+    @IBOutlet var opacityLabel: NSTextField!
+    @IBOutlet var opacityNewLabel: NSTextField!
+    @IBOutlet var opacityNewTextField: NSTextField!
+    @IBOutlet var opacityNewStepper: NSStepper!
+    @IBOutlet var opacityOldLabel: NSTextField!
+    @IBOutlet var opacityOldTextField: NSTextField!
+    @IBOutlet var opacityOldStepper: NSStepper!
+    @IBOutlet var separatorLine1: NSView!
+    @IBOutlet var separatorLine2: NSView!
+    @IBOutlet var strokeColorLabel: NSTextField!
+    @IBOutlet var strokeNewColorLabel: NSTextField!
+    @IBOutlet var strokeNewColorWell: NSColorWell!
+    @IBOutlet var strokeOldColorLabel: NSTextField!
+    @IBOutlet var strokeOldWell: NSColorWell!
+    @IBOutlet var modelLabel: NSTextField!
+    @IBOutlet var modelComboBox: NSComboBox!
+    @IBOutlet var filledButton: NSButton!
+
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+    }
+
+    override func setup() {
+        NSColorPanel.shared.showsAlpha = true
+        separatorLine1.wantsLayer = true
+        separatorLine2.wantsLayer = true
+        NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
+        modelComboBox.isEditable = false
+    }
+    
+    override func reloadData() {
+        let config = KMCompareFilesConfig.defaultConfig
+        
+        var oldStrokeColor = config.oldStrokeColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        oldStrokeColor = oldStrokeColor?.withAlphaComponent(config.oldStrokeOpacity())
+
+        var newStrokeColor = config.newStrokeColor().usingColorSpaceName(NSColorSpaceName.calibratedRGB)
+        newStrokeColor = newStrokeColor?.withAlphaComponent(config.newStrokeOpacity())
+
+        strokeOldWell.color = oldStrokeColor!
+        strokeNewColorWell.color = newStrokeColor!
+
+        opacityNewTextField.stringValue = String(format: "%.0f", config.newFillOpacity() * 100)
+        opacityOldTextField.stringValue = String(format: "%.0f", config.oldFillOpacity() * 100)
+
+        opacityOldStepper.floatValue = Float(config.oldFillOpacity() * 100)
+        opacityNewStepper.floatValue = Float(config.newFillOpacity() * 100)
+
+        filledButton.state = config.isNOFill() ? .on : .off
+        modelComboBox.selectItem(at: config.blendMod().rawValue)
+        
+    }
+    
+    override func updateLanguage() {
+        opacityLabel.stringValue = NSLocalizedString("Document Opacity", comment: "")
+        opacityNewLabel.stringValue = NSLocalizedString("New File:", comment: "")
+        opacityOldLabel.stringValue = NSLocalizedString("Old File:", comment: "")
+        strokeColorLabel.stringValue = NSLocalizedString("Stroke Color:", comment: "")
+        strokeNewColorLabel.stringValue = NSLocalizedString("New File:", comment: "")
+        strokeOldColorLabel.stringValue = NSLocalizedString("Old File:", comment: "")
+        modelLabel.stringValue = NSLocalizedString("Blend Mode:", comment: "")
+        filledButton.title = NSLocalizedString("Fill the white box (some content will be covered)", comment: "")
+        filledButton.toolTip = NSLocalizedString("Fill the white box (some content will be covered)", comment: "")
+
+        modelComboBox.addItems(withObjectValues: [NSLocalizedString("Normal", comment: ""),
+                                                  NSLocalizedString("Multiply", comment: ""),
+                                                  NSLocalizedString("Darken", comment: ""),
+                                                  NSLocalizedString("ColorBurn", comment: ""),
+                                                  NSLocalizedString("Hard Light", comment: ""),
+                                                  NSLocalizedString("Difference", comment: ""),
+                                                  NSLocalizedString("Exclusion", comment: ""),
+                                                  NSLocalizedString("Luminosity", comment: "")])
+    }
+    
+    @objc override func updateUI() {
+        if KMAppearance.isDarkMode() {
+            separatorLine1.layer?.backgroundColor = NSColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 0.5).cgColor
+            separatorLine2.layer?.backgroundColor = NSColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 0.5).cgColor
+        } else {
+            separatorLine1.layer?.backgroundColor = NSColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 0.1).cgColor
+            separatorLine2.layer?.backgroundColor = NSColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 0.1).cgColor
+        }
+    }
+
+    // MARK: - Actions
+    @IBAction func opacityOldStepperAction(_ sender: NSStepper) {
+        let config = KMCompareFilesConfig.defaultConfig
+        var floatValue = sender.floatValue
+        sender.floatValue = floatValue
+        if floatValue < 0 {
+            floatValue = 0
+        } else if floatValue > 100 {
+            floatValue = 100
+        }
+        opacityOldTextField.stringValue = String(format: "%.0f", floatValue)
+        config.setOldFillOpacity(CGFloat(floatValue) / 100.0)
+    }
+
+    @IBAction func opacityNewStepperAction(_ sender: NSStepper) {
+        let config = KMCompareFilesConfig.defaultConfig
+        var floatValue = sender.floatValue
+        sender.integerValue = Int(floatValue)
+        if floatValue < 0 {
+            floatValue = 0
+        } else if floatValue > 100 {
+            floatValue = 100
+        }
+        opacityNewTextField.stringValue = String(format: "%.0f", floatValue)
+        config.setNewFillOpacity(CGFloat(floatValue) / 100.0)
+    }
+
+    @IBAction func strokeOldColorWellChanged(_ sender: NSColorWell) {
+        if let color = sender.color.usingColorSpaceName(NSColorSpaceName.calibratedRGB) {
+            let config = KMCompareFilesConfig.defaultConfig
+            config.setOldStrokeColor(color)
+            config.setOldStrokeOpacity(color.alphaComponent)
+        }
+    }
+
+    @IBAction func strokeNewColorWellChanged(_ sender: NSColorWell) {
+        if let color = sender.color.usingColorSpaceName(NSColorSpaceName.calibratedRGB) {
+            let config = KMCompareFilesConfig.defaultConfig
+            config.setNewStrokeColor(color)
+            config.setNewStrokeOpacity(color.alphaComponent)
+        }
+    }
+
+    @IBAction func comboBoxItemClick_Moel(_ sender: NSComboBox) {
+        let config = KMCompareFilesConfig.defaultConfig
+        config.setBlendMod(CPDFBlendMode.init(rawValue: sender.indexOfSelectedItem)!)
+    }
+
+    @IBAction func comboBoxItemClick_Fill(_ sender: NSButton) {
+        let config = KMCompareFilesConfig.defaultConfig
+
+        if filledButton.state == .on {
+            config.setIsNOFill(true)
+        } else {
+            config.setIsNOFill(false)
+        }
+    }
+
+    // MARK: - NSTextFieldDelegate
+    func controlTextDidChange(_ notification: Notification) {
+        guard let textField = notification.object as? NSTextField else { return }
+        let config = KMCompareFilesConfig.defaultConfig
+
+        if opacityNewTextField == textField {
+            var floatValue = textField.floatValue
+            if floatValue < 0 {
+                floatValue = 0
+                textField.stringValue = String(format: ".0%f", floatValue)
+            } else if floatValue > 100 {
+                floatValue = 100
+                textField.stringValue = String(format: ".0%f", floatValue)
+            }
+            opacityNewTextField.stringValue = String(format: "%.0f", floatValue)
+            config.setNewFillOpacity(CGFloat(floatValue) / 100.0)
+        } else if opacityOldTextField == textField {
+            var floatValue = textField.floatValue
+            if floatValue < 0 {
+                floatValue = 0
+                textField.stringValue = String(format: ".0%f", floatValue)
+            } else if floatValue > 100 {
+                floatValue = 100
+                textField.stringValue = String(format: ".0%f", floatValue)
+            }
+            opacityOldTextField.stringValue = String(format: "%.0f", floatValue)
+            config.setOldFillOpacity(CGFloat(floatValue) / 100.0)
+        }
+    }
+
+    func controlTextDidEndEditing(_ notification: Notification) {
+        guard let textField = notification.object as? NSTextField else { return }
+        let config = KMCompareFilesConfig.defaultConfig
+
+        if opacityNewTextField == textField {
+            var floatValue = textField.floatValue
+            if floatValue < 0 {
+                floatValue = 0
+                textField.stringValue = String(format: ".0%f", floatValue)
+            } else if floatValue > 100 {
+                floatValue = 100
+                textField.stringValue = String(format: ".0%f", floatValue)
+            }
+            opacityNewTextField.stringValue = String(format: "%.0f", floatValue)
+            config.setNewFillOpacity(CGFloat(floatValue) / 100.0)
+        } else if opacityOldTextField == textField {
+            var floatValue = textField.floatValue
+            if floatValue < 0 {
+                floatValue = 0
+                textField.stringValue = String(format: ".0%f", floatValue)
+            } else if floatValue > 100 {
+                floatValue = 100
+                textField.stringValue = String(format: ".0%f", floatValue)
+            }
+            opacityOldTextField.stringValue = String(format: "%.0f", floatValue)
+            config.setOldFillOpacity(CGFloat(floatValue) / 100.0)
+        }
+    }
+}

+ 354 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/CoveringSetting/View/KMCompareCoveringSettingView.xib

@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareCoveringSettingView" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="coveringCompareBox" destination="pyH-7F-pAI" id="Do2-W9-bRc"/>
+                <outlet property="filledButton" destination="R33-CA-cf8" id="VYw-6N-oxU"/>
+                <outlet property="modelComboBox" destination="xJe-cV-f39" id="5gK-ol-sfR"/>
+                <outlet property="modelLabel" destination="35E-K7-KWg" id="f56-TZ-yGx"/>
+                <outlet property="opacityLabel" destination="Hl0-TI-eeE" id="1Mg-zr-rvC"/>
+                <outlet property="opacityNewLabel" destination="P50-QV-3oq" id="v4s-Mb-MMg"/>
+                <outlet property="opacityNewStepper" destination="emF-kg-sPl" id="nE0-IU-567"/>
+                <outlet property="opacityNewTextField" destination="3Mk-Yo-ZPN" id="dcI-ht-kMt"/>
+                <outlet property="opacityOldLabel" destination="kHX-6X-SXY" id="7Rw-rh-JuR"/>
+                <outlet property="opacityOldStepper" destination="WIC-Dg-Dp2" id="PIC-Vc-A5K"/>
+                <outlet property="opacityOldTextField" destination="kbx-lx-Fp4" id="HZd-vz-Zt9"/>
+                <outlet property="separatorLine1" destination="Oaa-t4-p6S" id="TgB-Tn-fbq"/>
+                <outlet property="separatorLine2" destination="yZf-MY-KRN" id="nQx-PF-5Hs"/>
+                <outlet property="strokeColorLabel" destination="YEy-6O-hWz" id="mFO-Jl-4Uv"/>
+                <outlet property="strokeNewColorLabel" destination="H8F-We-LRz" id="I3N-sy-a4K"/>
+                <outlet property="strokeNewColorWell" destination="nId-OX-zQu" id="fel-ps-lw6"/>
+                <outlet property="strokeOldColorLabel" destination="B7d-O7-iaZ" id="mmQ-sH-88p"/>
+                <outlet property="strokeOldWell" destination="CG1-Qf-6H5" id="hch-WE-2sl"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <view translatesAutoresizingMaskIntoConstraints="NO" id="lgg-g5-79H">
+                    <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
+                    <subviews>
+                        <customView translatesAutoresizingMaskIntoConstraints="NO" id="yI6-Qw-VBo">
+                            <rect key="frame" x="77" y="18" width="326" height="236"/>
+                            <subviews>
+                                <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="pyH-7F-pAI">
+                                    <rect key="frame" x="0.0" y="0.0" width="326" height="236"/>
+                                    <view key="contentView" id="FjY-dh-6Bp">
+                                        <rect key="frame" x="0.0" y="0.0" width="326" height="236"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Hl0-TI-eeE">
+                                                <rect key="frame" x="0.0" y="220" width="328" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="324" id="PMx-zd-2AB"/>
+                                                    <constraint firstAttribute="height" constant="16" id="mlo-GQ-Kdo"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Fill Opacity" id="ky7-e1-eVz">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kHX-6X-SXY">
+                                                <rect key="frame" x="0.0" y="194" width="98" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="BNG-aD-50V"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Old Documents" id="tww-br-LPS">
+                                                    <font key="font" metaFont="system"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kbx-lx-Fp4">
+                                                <rect key="frame" x="104" y="192" width="60" height="20"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="60" id="844-cR-kG2"/>
+                                                    <constraint firstAttribute="height" constant="20" id="r8l-Hj-4XF"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" title="50" drawsBackground="YES" id="eVy-v0-Y2p">
+                                                    <font key="font" metaFont="system"/>
+                                                    <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Tqb-VX-aVE">
+                                                <rect key="frame" x="164" y="194" width="16" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="12" id="EJ0-Wd-1BC"/>
+                                                    <constraint firstAttribute="height" constant="16" id="Jvv-u5-Cml"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="%" id="UZT-9V-c0R">
+                                                    <font key="font" metaFont="system"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="WIC-Dg-Dp2">
+                                                <rect key="frame" x="179" y="188" width="19" height="28"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="20" id="6nM-xv-nAD"/>
+                                                    <constraint firstAttribute="width" constant="13" id="niG-T1-4YL"/>
+                                                </constraints>
+                                                <stepperCell key="cell" continuous="YES" alignment="left" maxValue="100" id="ynA-mS-YCI"/>
+                                                <connections>
+                                                    <action selector="opacityOldStepperAction:" target="-2" id="gAM-gg-BIu"/>
+                                                </connections>
+                                            </stepper>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="P50-QV-3oq">
+                                                <rect key="frame" x="0.0" y="166" width="104" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="6Yb-ay-JxT"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="New Documents" id="AOl-GL-0Jj">
+                                                    <font key="font" metaFont="system"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3Mk-Yo-ZPN">
+                                                <rect key="frame" x="110" y="164" width="60" height="20"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="20" id="iRy-Tj-Xdq"/>
+                                                    <constraint firstAttribute="width" constant="60" id="m8b-j5-exQ"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" title="50" drawsBackground="YES" id="sHG-Vy-5y4">
+                                                    <font key="font" metaFont="system"/>
+                                                    <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="a8x-jR-tLo">
+                                                <rect key="frame" x="170" y="166" width="16" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="12" id="M6J-CL-dQk"/>
+                                                    <constraint firstAttribute="height" constant="16" id="O4h-Y3-Al1"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="%" id="NDb-iu-NtA">
+                                                    <font key="font" metaFont="system"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="emF-kg-sPl">
+                                                <rect key="frame" x="185" y="160" width="19" height="28"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="13" id="Syi-LS-24g"/>
+                                                    <constraint firstAttribute="height" constant="20" id="sEN-B7-vXF"/>
+                                                </constraints>
+                                                <stepperCell key="cell" continuous="YES" alignment="left" maxValue="100" id="DOd-4Z-Eqc"/>
+                                                <connections>
+                                                    <action selector="opacityNewStepperAction:" target="-2" id="O8H-1h-INv"/>
+                                                </connections>
+                                            </stepper>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="Oaa-t4-p6S">
+                                                <rect key="frame" x="0.0" y="155" width="326" height="1"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="1" id="I19-rQ-EC6"/>
+                                                    <constraint firstAttribute="width" constant="326" id="owf-Hr-Nht"/>
+                                                </constraints>
+                                            </customView>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="YEy-6O-hWz">
+                                                <rect key="frame" x="0.0" y="129" width="328" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="9ha-hU-noZ"/>
+                                                    <constraint firstAttribute="width" constant="324" id="nUX-kG-mdT"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Stroke Color:" id="keQ-be-DsE">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="B7d-O7-iaZ">
+                                                <rect key="frame" x="0.0" y="103" width="98" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="umE-aa-pMS"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Old Documents" id="Lxu-UV-gIS">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="H8F-We-LRz">
+                                                <rect key="frame" x="0.0" y="73" width="104" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="fD8-EV-VPl"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="New Documents" id="VWU-Kx-fMI">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <colorWell translatesAutoresizingMaskIntoConstraints="NO" id="nId-OX-zQu">
+                                                <rect key="frame" x="107" y="71" width="40" height="20"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="width" constant="34" id="BXW-mj-YaU"/>
+                                                    <constraint firstAttribute="height" constant="16" id="dr7-x8-qJz"/>
+                                                </constraints>
+                                                <color key="color" red="0.05813049898" green="0.055541899059999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                                <connections>
+                                                    <action selector="strokeNewColorWellChanged:" target="-2" id="Zu0-68-pYl"/>
+                                                </connections>
+                                            </colorWell>
+                                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="yZf-MY-KRN">
+                                                <rect key="frame" x="0.0" y="60" width="326" height="1"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="1" id="Iep-rs-H2c"/>
+                                                    <constraint firstAttribute="width" constant="326" id="ju3-CB-lkU"/>
+                                                </constraints>
+                                            </customView>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="35E-K7-KWg">
+                                                <rect key="frame" x="0.0" y="32" width="39" height="16"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="oOh-EM-PuJ"/>
+                                                </constraints>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Mode" id="Nw4-kK-XqI">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <comboBox verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xJe-cV-f39">
+                                                <rect key="frame" x="44" y="28" width="154" height="23"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="20" id="ZgU-Og-pnU"/>
+                                                    <constraint firstAttribute="width" constant="150" id="o9S-I2-ra6"/>
+                                                </constraints>
+                                                <comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" completes="NO" numberOfVisibleItems="5" id="jz9-7q-aHT">
+                                                    <font key="font" metaFont="system"/>
+                                                    <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </comboBoxCell>
+                                                <connections>
+                                                    <action selector="comboBoxItemClick_Moel:" target="-2" id="rVL-CR-GNR"/>
+                                                </connections>
+                                            </comboBox>
+                                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="R33-CA-cf8">
+                                                <rect key="frame" x="0.0" y="3" width="326" height="18"/>
+                                                <buttonCell key="cell" type="check" title="Fill the white box (some content will be covered)" bezelStyle="regularSquare" imagePosition="left" lineBreakMode="truncatingTail" state="on" inset="2" id="2aa-Mj-HHh">
+                                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+                                                    <font key="font" metaFont="system"/>
+                                                </buttonCell>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="YwN-bC-3nO"/>
+                                                </constraints>
+                                                <connections>
+                                                    <action selector="comboBoxItemClick_Fill:" target="-2" id="o8E-NK-zIS"/>
+                                                </connections>
+                                            </button>
+                                            <colorWell translatesAutoresizingMaskIntoConstraints="NO" id="CG1-Qf-6H5">
+                                                <rect key="frame" x="101" y="101" width="40" height="20"/>
+                                                <constraints>
+                                                    <constraint firstAttribute="height" constant="16" id="4OE-0N-Rte"/>
+                                                    <constraint firstAttribute="width" constant="34" id="vwl-3y-3oK"/>
+                                                </constraints>
+                                                <color key="color" red="0.05813049898" green="0.055541899059999997" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                                <connections>
+                                                    <action selector="strokeOldColorWellChanged:" target="-2" id="qct-FX-Wvd"/>
+                                                </connections>
+                                            </colorWell>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstItem="emF-kg-sPl" firstAttribute="centerY" secondItem="P50-QV-3oq" secondAttribute="centerY" id="1JS-zf-oRS"/>
+                                            <constraint firstItem="emF-kg-sPl" firstAttribute="leading" secondItem="a8x-jR-tLo" secondAttribute="trailing" constant="4" id="3uc-MK-VEP"/>
+                                            <constraint firstItem="YEy-6O-hWz" firstAttribute="top" secondItem="Oaa-t4-p6S" secondAttribute="bottom" constant="10" id="5Fn-Uq-d84"/>
+                                            <constraint firstAttribute="trailing" secondItem="R33-CA-cf8" secondAttribute="trailing" id="5if-Sw-498"/>
+                                            <constraint firstItem="WIC-Dg-Dp2" firstAttribute="centerY" secondItem="kHX-6X-SXY" secondAttribute="centerY" id="8Rd-9J-WtN"/>
+                                            <constraint firstItem="CG1-Qf-6H5" firstAttribute="leading" secondItem="B7d-O7-iaZ" secondAttribute="trailing" constant="8" id="8iq-XK-3tk"/>
+                                            <constraint firstItem="emF-kg-sPl" firstAttribute="leading" secondItem="a8x-jR-tLo" secondAttribute="trailing" constant="4" id="8nc-9d-OY8"/>
+                                            <constraint firstItem="B7d-O7-iaZ" firstAttribute="top" secondItem="YEy-6O-hWz" secondAttribute="bottom" constant="10" id="93X-aR-Hqn"/>
+                                            <constraint firstItem="Tqb-VX-aVE" firstAttribute="centerY" secondItem="kHX-6X-SXY" secondAttribute="centerY" id="9Eo-OD-PFf"/>
+                                            <constraint firstItem="nId-OX-zQu" firstAttribute="top" secondItem="CG1-Qf-6H5" secondAttribute="bottom" constant="14" id="9TQ-lK-SiB"/>
+                                            <constraint firstAttribute="trailing" secondItem="Oaa-t4-p6S" secondAttribute="trailing" id="9cn-sn-TGg"/>
+                                            <constraint firstItem="yZf-MY-KRN" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" id="A2a-Xa-JwH"/>
+                                            <constraint firstItem="yZf-MY-KRN" firstAttribute="top" secondItem="nId-OX-zQu" secondAttribute="bottom" constant="12" id="CJr-i2-jRf"/>
+                                            <constraint firstItem="CG1-Qf-6H5" firstAttribute="centerY" secondItem="B7d-O7-iaZ" secondAttribute="centerY" id="Cc9-c0-VGG"/>
+                                            <constraint firstItem="kbx-lx-Fp4" firstAttribute="leading" secondItem="kHX-6X-SXY" secondAttribute="trailing" constant="8" id="Ced-fS-LoN"/>
+                                            <constraint firstItem="Oaa-t4-p6S" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" id="CuJ-R3-VkC"/>
+                                            <constraint firstItem="P50-QV-3oq" firstAttribute="top" secondItem="kHX-6X-SXY" secondAttribute="bottom" constant="12" id="DaG-Mc-1zb"/>
+                                            <constraint firstItem="P50-QV-3oq" firstAttribute="top" secondItem="kHX-6X-SXY" secondAttribute="bottom" constant="12" id="DkW-2d-k2Q"/>
+                                            <constraint firstItem="P50-QV-3oq" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="EB3-tb-Cbz"/>
+                                            <constraint firstItem="YEy-6O-hWz" firstAttribute="top" secondItem="Oaa-t4-p6S" secondAttribute="bottom" constant="10" id="EFL-J7-UgY"/>
+                                            <constraint firstItem="R33-CA-cf8" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="Fx0-D9-d0s"/>
+                                            <constraint firstItem="nId-OX-zQu" firstAttribute="leading" secondItem="H8F-We-LRz" secondAttribute="trailing" constant="8" id="G0k-Ub-F5b"/>
+                                            <constraint firstItem="H8F-We-LRz" firstAttribute="top" secondItem="B7d-O7-iaZ" secondAttribute="bottom" constant="14" id="JOC-Nc-aJz"/>
+                                            <constraint firstItem="a8x-jR-tLo" firstAttribute="leading" secondItem="3Mk-Yo-ZPN" secondAttribute="trailing" constant="2" id="JON-og-0d0"/>
+                                            <constraint firstItem="R33-CA-cf8" firstAttribute="top" secondItem="35E-K7-KWg" secondAttribute="bottom" constant="12" id="LZJ-nE-elp"/>
+                                            <constraint firstItem="a8x-jR-tLo" firstAttribute="centerY" secondItem="P50-QV-3oq" secondAttribute="centerY" id="M4b-Dx-1Un"/>
+                                            <constraint firstItem="kHX-6X-SXY" firstAttribute="top" secondItem="Hl0-TI-eeE" secondAttribute="bottom" constant="10" id="N41-tX-JZ2"/>
+                                            <constraint firstItem="yZf-MY-KRN" firstAttribute="top" secondItem="H8F-We-LRz" secondAttribute="bottom" constant="12" id="OfA-bU-WUt"/>
+                                            <constraint firstItem="B7d-O7-iaZ" firstAttribute="top" secondItem="YEy-6O-hWz" secondAttribute="bottom" constant="10" id="OrK-ke-HV0"/>
+                                            <constraint firstItem="Tqb-VX-aVE" firstAttribute="leading" secondItem="kbx-lx-Fp4" secondAttribute="trailing" constant="2" id="S66-1S-yXb"/>
+                                            <constraint firstItem="Hl0-TI-eeE" firstAttribute="top" secondItem="FjY-dh-6Bp" secondAttribute="top" id="TeI-qI-ubA"/>
+                                            <constraint firstItem="35E-K7-KWg" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="Tfn-gl-fKZ"/>
+                                            <constraint firstItem="yZf-MY-KRN" firstAttribute="top" secondItem="H8F-We-LRz" secondAttribute="bottom" constant="12" id="VY6-iP-gNO"/>
+                                            <constraint firstItem="kHX-6X-SXY" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="Vjh-PR-uGs"/>
+                                            <constraint firstItem="35E-K7-KWg" firstAttribute="top" secondItem="yZf-MY-KRN" secondAttribute="bottom" constant="12" id="Wqh-Sk-Y93"/>
+                                            <constraint firstAttribute="trailing" secondItem="yZf-MY-KRN" secondAttribute="trailing" id="Wy9-Vt-fkT"/>
+                                            <constraint firstItem="Hl0-TI-eeE" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="XE0-Nz-0Od"/>
+                                            <constraint firstItem="kbx-lx-Fp4" firstAttribute="centerY" secondItem="kHX-6X-SXY" secondAttribute="centerY" id="ZKx-Zq-Nr0"/>
+                                            <constraint firstItem="Oaa-t4-p6S" firstAttribute="top" secondItem="P50-QV-3oq" secondAttribute="bottom" constant="10" id="cYu-D4-qCw"/>
+                                            <constraint firstItem="R33-CA-cf8" firstAttribute="top" secondItem="xJe-cV-f39" secondAttribute="bottom" constant="10" id="cmn-vS-SRj"/>
+                                            <constraint firstItem="3Mk-Yo-ZPN" firstAttribute="centerY" secondItem="P50-QV-3oq" secondAttribute="centerY" id="deF-Yt-2eQ"/>
+                                            <constraint firstAttribute="bottom" secondItem="R33-CA-cf8" secondAttribute="bottom" constant="4" id="eE1-Pm-a1R"/>
+                                            <constraint firstItem="nId-OX-zQu" firstAttribute="centerY" secondItem="H8F-We-LRz" secondAttribute="centerY" id="edF-Oq-ZsT"/>
+                                            <constraint firstItem="xJe-cV-f39" firstAttribute="leading" secondItem="35E-K7-KWg" secondAttribute="trailing" constant="8" id="fjZ-y8-7nm"/>
+                                            <constraint firstAttribute="trailing" secondItem="Hl0-TI-eeE" secondAttribute="trailing" id="jHt-KB-aG5"/>
+                                            <constraint firstItem="xJe-cV-f39" firstAttribute="top" secondItem="yZf-MY-KRN" secondAttribute="bottom" constant="10" id="jQA-XY-8Mc"/>
+                                            <constraint firstItem="R33-CA-cf8" firstAttribute="top" secondItem="xJe-cV-f39" secondAttribute="bottom" constant="10" id="jxs-3Q-MLE"/>
+                                            <constraint firstItem="a8x-jR-tLo" firstAttribute="leading" secondItem="3Mk-Yo-ZPN" secondAttribute="trailing" constant="2" id="kC6-c7-0v6"/>
+                                            <constraint firstItem="3Mk-Yo-ZPN" firstAttribute="leading" secondItem="P50-QV-3oq" secondAttribute="trailing" constant="8" id="lSi-bt-8F0"/>
+                                            <constraint firstItem="WIC-Dg-Dp2" firstAttribute="leading" secondItem="Tqb-VX-aVE" secondAttribute="trailing" constant="4" id="lgy-bx-2Fq"/>
+                                            <constraint firstItem="Tqb-VX-aVE" firstAttribute="leading" secondItem="kbx-lx-Fp4" secondAttribute="trailing" constant="2" id="mkv-13-tib"/>
+                                            <constraint firstItem="H8F-We-LRz" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="pP4-0Y-uuZ"/>
+                                            <constraint firstItem="H8F-We-LRz" firstAttribute="top" secondItem="B7d-O7-iaZ" secondAttribute="bottom" constant="14" id="r4d-iv-LOH"/>
+                                            <constraint firstItem="B7d-O7-iaZ" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="ryQ-uc-tdh"/>
+                                            <constraint firstItem="xJe-cV-f39" firstAttribute="centerY" secondItem="35E-K7-KWg" secondAttribute="centerY" id="sDR-2e-ntq"/>
+                                            <constraint firstItem="35E-K7-KWg" firstAttribute="top" secondItem="yZf-MY-KRN" secondAttribute="bottom" constant="12" id="sd3-Ov-Kfo"/>
+                                            <constraint firstItem="Oaa-t4-p6S" firstAttribute="top" secondItem="P50-QV-3oq" secondAttribute="bottom" constant="10" id="sdr-LR-V0z"/>
+                                            <constraint firstAttribute="trailing" secondItem="YEy-6O-hWz" secondAttribute="trailing" id="v3Z-FX-Scy"/>
+                                            <constraint firstItem="YEy-6O-hWz" firstAttribute="leading" secondItem="FjY-dh-6Bp" secondAttribute="leading" constant="2" id="xmg-mz-TZt"/>
+                                        </constraints>
+                                    </view>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="236" id="Nz7-va-2LH"/>
+                                        <constraint firstAttribute="width" constant="326" id="ilb-sc-jPu"/>
+                                    </constraints>
+                                </box>
+                            </subviews>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="326" id="2Nw-Yk-L9g"/>
+                                <constraint firstItem="pyH-7F-pAI" firstAttribute="centerY" secondItem="yI6-Qw-VBo" secondAttribute="centerY" id="DpA-Pu-tCR"/>
+                                <constraint firstItem="pyH-7F-pAI" firstAttribute="centerX" secondItem="yI6-Qw-VBo" secondAttribute="centerX" id="bx0-yy-Jgr"/>
+                                <constraint firstAttribute="height" constant="236" id="dsv-my-NX0"/>
+                            </constraints>
+                        </customView>
+                    </subviews>
+                    <constraints>
+                        <constraint firstItem="yI6-Qw-VBo" firstAttribute="centerX" secondItem="lgg-g5-79H" secondAttribute="centerX" id="8sB-vS-tDe"/>
+                        <constraint firstItem="yI6-Qw-VBo" firstAttribute="centerY" secondItem="lgg-g5-79H" secondAttribute="centerY" id="LRT-ph-9d3"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <constraints>
+                <constraint firstItem="lgg-g5-79H" firstAttribute="top" secondItem="c22-O7-iKe" secondAttribute="top" id="2qK-mj-dyJ"/>
+                <constraint firstAttribute="trailing" secondItem="lgg-g5-79H" secondAttribute="trailing" id="3Kl-oM-cwe"/>
+                <constraint firstItem="lgg-g5-79H" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="JXr-em-n5v"/>
+                <constraint firstAttribute="bottom" secondItem="lgg-g5-79H" secondAttribute="bottom" id="SoQ-QH-HpD"/>
+            </constraints>
+            <point key="canvasLocation" x="-28" y="116"/>
+        </customView>
+    </objects>
+</document>

+ 25 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/KMCompareSaveWindow.swift

@@ -0,0 +1,25 @@
+//
+//  KMCompareSaveWindow.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/22.
+//
+
+import Cocoa
+
+class KMCompareSaveWindow: NSWindowController {
+
+    @IBOutlet weak var saveView: KMCompareSaveView!
+    
+    var fileSaveFolderPath = ""
+    
+    var cancelHandle:((_ controller: KMCompareSaveWindow) -> Void)?
+    var saveHandle:((_ controller: KMCompareSaveWindow, _ saveType: Int) -> Void)?
+    
+    override func windowDidLoad() {
+        super.windowDidLoad()
+
+        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
+    }
+    
+}

+ 43 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/KMCompareSaveWindow.xib

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCompareSaveWindow" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="saveView" destination="z93-rP-BUM" id="wSs-1l-yfc"/>
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="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="2560" height="1415"/>
+            <view key="contentView" id="se5-gp-TjO">
+                <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <customView translatesAutoresizingMaskIntoConstraints="NO" id="z93-rP-BUM" customClass="KMCompareSaveView" customModule="PDF_Master" customModuleProvider="target">
+                        <rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
+                    </customView>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="bottom" secondItem="z93-rP-BUM" secondAttribute="bottom" id="1mJ-gI-eCe"/>
+                    <constraint firstItem="z93-rP-BUM" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" id="Dzi-Eb-L5t"/>
+                    <constraint firstItem="z93-rP-BUM" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" id="K3P-aP-l75"/>
+                    <constraint firstAttribute="trailing" secondItem="z93-rP-BUM" secondAttribute="trailing" id="m6C-W2-cG4"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
+            </connections>
+            <point key="canvasLocation" x="-27" y="114"/>
+        </window>
+    </objects>
+</document>

+ 126 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/View/KMCompareSaveView.swift

@@ -0,0 +1,126 @@
+//
+//  KMCompareSaveView.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/11/22.
+//
+
+class KMCompareSaveView: KMBaseXibView {
+
+    @IBOutlet weak var contendView: NSView!
+    @IBOutlet weak var saveAsLbl: NSTextField!
+
+    @IBOutlet weak var docTypeBox: NSBox!
+    @IBOutlet weak var oldDocTypeBtn: NSButton!
+    @IBOutlet weak var nDocTypeBtn: NSButton!
+    @IBOutlet weak var mergeDocTypeBtn: NSButton!
+
+    @IBOutlet weak var seplineView: NSView!
+    @IBOutlet weak var fileLocationTipLbl: NSTextField!
+
+    @IBOutlet weak var outputBackView: NSView!
+    @IBOutlet weak var outputText: NSTextField!
+    @IBOutlet weak var outputButton: NSButton!
+
+    @IBOutlet weak var cancelBtn: NSButton!
+    @IBOutlet weak var saveAsBtn: NSButton!
+
+    var fileSaveFolderPath = ""
+    var saveType = 0
+    
+    var cancelHandle:((_ view: KMCompareSaveView) -> Void)?
+    var saveHandle:((_ view: KMCompareSaveView, _ saveType: Int) -> Void)?
+    
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+    
+    override func setup() {
+        let desktopPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
+        fileSaveFolderPath = desktopPath
+        outputText.stringValue = fileSaveFolderPath
+
+        refreshDocType()
+
+        NotificationCenter.default.addObserver(self, selector: #selector(themeChanged(_:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
+    }
+    
+    override func updateLanguage() {
+        saveAsLbl.stringValue = NSLocalizedString("Save as", comment: "")
+        oldDocTypeBtn.title = NSLocalizedString("Old File", comment: "")
+        nDocTypeBtn.title = NSLocalizedString("New File", comment: "")
+        mergeDocTypeBtn.title = NSLocalizedString("Merge into a New File", comment: "")
+        fileLocationTipLbl.stringValue = NSLocalizedString("File Location:", comment: "")
+        outputButton.title = NSLocalizedString("Choose", comment: "")
+        cancelBtn.title = NSLocalizedString("Cancel", comment: "")
+        saveAsBtn.title = NSLocalizedString("Save", comment: "")
+    }
+
+    override func updateUI() {
+        oldDocTypeBtn.contentTintColor = KMAppearance.Layout.h0Color()
+        nDocTypeBtn.contentTintColor = KMAppearance.Layout.h0Color()
+        mergeDocTypeBtn.contentTintColor = KMAppearance.Layout.h0Color()
+
+        fileLocationTipLbl.textColor = KMAppearance.Layout.h0Color()
+
+        if KMAppearance.isDarkMode() {
+            saveAsLbl.textColor = NSColor.white.withAlphaComponent(0.85)
+            docTypeBox.borderColor = NSColor.white.withAlphaComponent(0.05)
+            docTypeBox.fillColor = NSColor.white.withAlphaComponent(0.05)
+        } else {
+            saveAsLbl.textColor = NSColor.black.withAlphaComponent(0.85)
+            docTypeBox.borderColor = NSColor.black.withAlphaComponent(0.05)
+            docTypeBox.fillColor = NSColor.black.withAlphaComponent(0.05)
+        }
+    }
+
+    func refreshDocType() {
+        oldDocTypeBtn.state = saveType == 0 ? .on : .off
+        nDocTypeBtn.state = saveType == 1 ? .on : .off
+        mergeDocTypeBtn.state = saveType == 2 ? .on : .off
+    }
+
+    @IBAction func docTypeBtnAction(_ sender: NSButton) {
+        if sender == oldDocTypeBtn {
+            saveType = 0
+        } else if sender == nDocTypeBtn {
+            saveType = 1
+        } else if sender == mergeDocTypeBtn {
+            saveType = 2
+        }
+        refreshDocType()
+    }
+
+    @IBAction func chooseFileLocation(_ sender: NSButton) {
+        let panel = NSOpenPanel()
+        panel.canChooseFiles = false
+        panel.canChooseDirectories = true
+        panel.allowsMultipleSelection = false
+        panel.directoryURL = URL(fileURLWithPath: fileSaveFolderPath)
+
+        panel.beginSheetModal(for: self.window!) { response in
+            if response == .OK {
+                self.fileSaveFolderPath = panel.url?.path ?? ""
+                self.outputText.stringValue = self.fileSaveFolderPath
+            }
+        }
+    }
+
+    @IBAction func cancelAction(_ sender: Any) {
+        if let cancelHandle = cancelHandle {
+            cancelHandle(self)
+        }
+    }
+
+    @IBAction func saveAsAction(_ sender: Any) {
+        if let saveHandle = saveHandle {
+            saveHandle(self, saveType)
+        }
+    }
+
+    @objc func themeChanged(_ notification: Notification) {
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+            self.updateUI()
+        }
+    }
+}

+ 15 - 0
PDF Office/PDF Master/Class/PDFTools/Compare/ViewController/Save/View/KMCompareSaveView.xib

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11134" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11134"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe">
+            <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+        </customView>
+    </objects>
+</document>

+ 13 - 13
PDF Office/PDF Master/Class/PDFTools/Crop/KMCropSettingWindowController.xib

@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21225" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>
-        <customObject id="-2" userLabel="File's Owner" customClass="KMCropSettingWindowController" customModule="PDF_Office" customModuleProvider="target">
+        <customObject id="-2" userLabel="File's Owner" customClass="KMCropSettingWindowController" customModule="PDF_Master" customModuleProvider="target">
             <connections>
                 <outlet property="applyButton" destination="4S4-1o-RqV" id="wA8-IB-9JC"/>
                 <outlet property="cancelButton" destination="XXB-iS-n7Y" id="NBS-hq-aJj"/>
@@ -22,7 +22,7 @@
             <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
             <rect key="contentRect" x="196" y="240" width="340" height="300"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1440" height="875"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
             <value key="minSize" type="size" width="340" height="300"/>
             <value key="maxSize" type="size" width="340" height="300"/>
             <value key="minFullScreenContentSize" type="size" width="340" height="300"/>
@@ -37,7 +37,7 @@
                             <rect key="frame" x="0.0" y="0.0" width="340" height="44"/>
                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                             <subviews>
-                                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xlm-BU-ieV">
+                                <textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xlm-BU-ieV">
                                     <rect key="frame" x="18" y="13" width="44" height="19"/>
                                     <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="ofd-Jo-wTH">
                                         <font key="font" metaFont="system" size="16"/>
@@ -103,25 +103,25 @@
                                 </box>
                                 <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4S4-1o-RqV">
                                     <rect key="frame" x="224" y="14" width="100" height="32"/>
-                                    <constraints>
-                                        <constraint firstAttribute="width" constant="100" id="6fn-9K-TYQ"/>
-                                        <constraint firstAttribute="height" constant="32" id="xnD-3s-RQ0"/>
-                                    </constraints>
                                     <buttonCell key="cell" type="bevel" title="Button" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="XNo-Og-jMa">
                                         <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                                         <font key="font" metaFont="system"/>
                                     </buttonCell>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="100" id="6fn-9K-TYQ"/>
+                                        <constraint firstAttribute="height" constant="32" id="xnD-3s-RQ0"/>
+                                    </constraints>
                                 </button>
                                 <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XXB-iS-n7Y">
                                     <rect key="frame" x="112" y="14" width="100" height="32"/>
-                                    <constraints>
-                                        <constraint firstAttribute="height" constant="32" id="eg6-3u-8Oe"/>
-                                        <constraint firstAttribute="width" constant="100" id="thm-Sz-L99"/>
-                                    </constraints>
                                     <buttonCell key="cell" type="bevel" title="Button" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="3ZJ-Dy-yKV">
                                         <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                                         <font key="font" metaFont="system"/>
                                     </buttonCell>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="32" id="eg6-3u-8Oe"/>
+                                        <constraint firstAttribute="width" constant="100" id="thm-Sz-L99"/>
+                                    </constraints>
                                 </button>
                             </subviews>
                             <constraints>

+ 122 - 0
PDF Office/PDF Master/Class/PDFWindowController/ViewController/KMMainViewController+Action.swift

@@ -3172,6 +3172,14 @@ extension KMMainViewController : KMMainToolbarControllerDelegate {
                     self.view.window?.endSheet((self.currentWindowController.window)!)
                     self.currentWindowController = nil
                 }
+                
+                controller.contentComplete = { [unowned self] controller, result, oldDocument, document in
+                    self.openContentCompareVC(with: controller.pdfCompareContent!, results: result, oldDocument: oldDocument, document: document)
+                }
+                
+                controller.coveringComplete = { [unowned self] controller, document in
+                    self.openCoveringCompareVC(with: document)
+                }
             
                 if index == 1 {
                     controller.fileType = .content
@@ -3665,3 +3673,117 @@ extension KMMainViewController {
             KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all)
     }
 }
+
+extension KMMainViewController {
+    func openContentCompareVC(with pdfCompareContent: CPDFCompareContent, results: [CPDFCompareResults], oldDocument: CPDFDocument, document: CPDFDocument) {
+        let contentController: KMCompareContentWindowController = KMCompareContentWindowController.init(document: document, oldDocument: oldDocument, results: results)
+        contentController.hideCloseInfo = true
+        contentController.saveHandle = { [unowned self] controller in
+            let saveController = KMCompareSaveWindow(windowNibName: "KMCompareSaveWindow")
+            saveController.cancelHandle = { [unowned self] controller in
+                NSWindow.currentWindow().endSheet(controller.window!)
+            }
+            
+            saveController.saveHandle = { [unowned self] controller, saveType in
+                let folderPath = controller.fileSaveFolderPath
+//#if VERSION_DMG
+//                
+//#else
+//                if let url = URL(string: folderPath) {
+//                    AppSandboxFileAccess.fileAccess().persistPermissionURL(url)
+//                    if let bookmarkData = try? url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil) {
+//                        AppSandboxFileAccess.fileAccess().bookmarkPersistanceDelegate?.setBookmarkData(bookmarkData, forURL: url)
+//                        AppSandboxFileAccess.fileAccess().bookmarkPersistanceDelegate?.setBookmarkData(bookmarkData, forURL: URL(fileURLWithPath: url.path))
+//                    }
+//                }
+//#endif
+                if folderPath != nil {
+                    if !FileManager.default.fileExists(atPath: folderPath) {
+                        try? FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil)
+                    }
+                    
+                    var savePath: String
+                    
+                    switch saveType {
+                    case 0:
+                        savePath = "\(folderPath)/\(oldDocument.documentURL.path.lastPathComponent.deletingPathExtension)_compare.\(oldDocument.documentURL.path.extension)"
+                        savePath = self.getValidFilePath(savePath)
+                        oldDocument.write(to: URL(fileURLWithPath: savePath))
+                        NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
+                    case 1:
+                        savePath = "\(folderPath)/\(document.documentURL.path.lastPathComponent.deletingPathExtension)_compare.\(document.documentURL.path.extension)"
+                        savePath = self.getValidFilePath(savePath)
+                        document.write(to: URL(fileURLWithPath: savePath))
+                        NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
+                    case 2:
+                        savePath = "\(folderPath)/MergedCompareFile.\(oldDocument.documentURL.path.extension)"
+                        savePath = self.getValidFilePath(savePath)
+                        pdfCompareContent.saveAsComparisonDocument(withFilePath: savePath)
+                        NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
+                    default:
+                        break
+                    }
+                }
+                
+                NSWindow.currentWindow().endSheet(controller.window!)
+            }
+        }
+        
+        contentController.closeHandle = { [unowned self] controller in
+            contentController.close()
+        }
+        NSWindow.currentWindow().km_beginSheet(windowC: contentController)
+    }
+
+    func getValidFilePath(_ oldPath: String) -> String {
+        let fileManager = FileManager.default
+
+        do {
+            let fileAttributes = try fileManager.attributesOfItem(atPath: oldPath)
+            guard let fileType = fileAttributes[FileAttributeKey.type] as? String else {
+                return oldPath
+            }
+
+            var i = 1
+            var newPath = oldPath
+
+            while fileManager.fileExists(atPath: newPath) {
+                if fileType == FileAttributeType.typeDirectory.rawValue {
+                    newPath = oldPath + "(\(i))"
+                } else {
+                    let fileExtension = (oldPath as NSString).pathExtension
+                    newPath = ((oldPath as NSString).deletingPathExtension as NSString).appendingFormat("(\(i)).\(fileExtension)" as NSString) as String
+                }
+                i += 1
+            }
+
+            return newPath
+        } catch {
+            print("Error getting file attributes: \(error)")
+            return oldPath
+        }
+    }
+
+    func openCoveringCompareVC(with pdfDocument: CPDFDocument) {
+        var coveringController: KMCompareCoveringWindowController = KMCompareCoveringWindowController.init(document: pdfDocument)
+        coveringController.hideCloseInfo = true
+        coveringController.saveHandle = { [unowned self] controller in
+            let savePanel = NSSavePanel()
+            savePanel.nameFieldStringValue = "untitled"
+            savePanel.allowedFileTypes = ["pdf"]
+            savePanel.beginSheetModal(for: controller.window!) { result in
+                if result == .OK {
+                    pdfDocument.write(to: savePanel.url!)
+                    NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!])
+                }
+            }
+        }
+        
+        coveringController.closeHandle = { [unowned self] controller in
+            NSWindow.currentWindow().endSheet(controller.window!)
+        }
+        
+        NSWindow.currentWindow().km_beginSheet(windowC: coveringController)
+    }
+
+}