|
@@ -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
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|