123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- //
- // KMPDFThumbnailView.swift
- // PDF Reader Pro
- //
- // Created by lxy on 2022/12/15.
- //
- class KMPDFThumbnailView: KMThumbnailView {
- var document: CPDFDocument?
- var isShowPageSize = false
- var thumbnailSzie = NSZeroSize
-
- //标记线
- var isNeedMarkerLine: Bool = false
- var markerLineView: NSView = NSView()
- var markBeginIndexes: IndexSet = IndexSet()
- //注释状态
- var annotationShowState: KMAnnotationViewShowType = .none {
- didSet {
- self.collectionView.reloadData()
- }
- }
- //悬浮
- var hoverIndex: Int = -1
-
- var filePromiseQueue: OperationQueue = {
- let queue = OperationQueue()
- return queue
- }()
-
- fileprivate var dragFilePath: String?
- fileprivate var dragFlag = false
- fileprivate var dragIn = false
-
- var limit = false
-
- override func initDefaultValue() {
- super.initDefaultValue()
-
- self.wantsLayer = true
- self.layer?.backgroundColor = NSColor.km_init(hex: "#F7F8FA").cgColor
-
- self.thumbnailSzie = CGSize(width: 120, height: 155)
- self.minimumLineSpacing = 8
- self.collectionView.km.register(cell: KMPDFThumbnailItem.self)
-
- self.collectionView.registerForDraggedTypes(NSFilePromiseReceiver.readableDraggedTypes.map { NSPasteboard.PasteboardType($0) })
- self.collectionView.setDraggingSourceOperationMask([.copy, .delete], forLocal: false)
- }
-
- override func initSubViews() {
- super.initSubViews()
-
- self.markerLineView.wantsLayer = true
- self.markerLineView.layer?.backgroundColor = NSColor.km_init(hex: "#1770F4").cgColor
- self.markerLineView.frame = NSMakeRect(0, 0, 100, 2)
- self.collectionView.addSubview(markerLineView)
- self.hiddenMarkerLineView()
- self.markerLineView.isHidden = true
- }
- }
- extension KMPDFThumbnailView {
- override func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
- if let size_ = self.delegate?.thumbnailView?(thumbanView: self, sizeForItemAt: indexPath) {
- return size_
- }
-
- var height: CGFloat = 0
- if let page = self.document?.page(at: UInt(indexPath.item)) {
- height = KMPDFThumbnailItem.sizeToFit(size: self.thumbnailSzie, page: page, isShow: self.isShowPageSize)
- }
-
- return NSMakeSize(collectionView.frame.size.width - 20, height)
- }
-
- override func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
- if let count = self.document?.pageCount {
- return Int(count)
- }
- return 0
- }
-
- override func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
- if let item = self.delegate?.thumbnailView?(thumbanView: self, itemForRepresentedObjectAt: indexPath) {
- return item
- }
- let cellView: KMPDFThumbnailItem = collectionView.km.dequeueReusableCell(for: indexPath)
- cellView.thumbnailView = self
- if let page_ = self.document?.page(at: UInt(indexPath.item)) {
- cellView.page = page_
- }
- cellView.annotationShowState = self.annotationShowState
- if indexPath.item == hoverIndex {
- cellView.hover = true
- } else {
- cellView.hover = false
- }
-
- cellView.mouseDownAction = { [unowned self] (view, event) in
- self.delegate?.thumbnailView?(thumbanView: self, didSelectItemAt: indexPath, object: event)
- }
-
- cellView.rightMouseDownAction = { [unowned self] (view, event) in
- self.delegate?.thumbnailView?(thumbanView: self, rightMouseDidClick: indexPath, item: view, object: event)
- }
-
- cellView.hoverCallBack = { [unowned self] view, mouseEntered in
- if let _ = self.collectionView.item(at: hoverIndex)?.view {
- let tempCell = self.collectionView.item(at: hoverIndex) as? KMPDFThumbnailItem
- tempCell?.hover = false
- }
-
- if mouseEntered {
- hoverIndex = indexPath.item
- if let _ = self.collectionView.item(at: hoverIndex)?.view {
- let tempCell = self.collectionView.item(at: hoverIndex) as? KMPDFThumbnailItem
- tempCell?.hover = true
- }
- } else {
- hoverIndex = -1
- }
- }
-
- return cellView
- }
-
- override func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItemsAt indexes: IndexSet) {
- if self.isNeedMarkerLine {
- self.markBeginIndexes = collectionView.selectionIndexes
- }
-
- // 将拖拽的page插入临时路径(文档)
- var indexs = IndexSet()
- for indexpath in self.dragedIndexPaths {
- indexs.insert(indexpath.item)
- }
- // 清空临时数据
- if let _path = self.dragTempFilePath, FileManager.default.fileExists(atPath: _path) {
- try?FileManager.default.removeItem(atPath: _path)
- }
-
- // 重置拖拽标识
- self.dragFlag = false
- if (indexs.count > 0) {
- let document = CPDFDocument()
- document?.importPages(indexs, from: self.document, at: 0)
- if let data = self.dragTempFloderPath, !FileManager.default.fileExists(atPath: data) {
- try?FileManager.default.createDirectory(atPath: data, withIntermediateDirectories: false)
- }
- if let data = self.dragTempFilePath, !FileManager.default.fileExists(atPath: data) {
- FileManager.default.createFile(atPath: data, contents: nil)
- }
-
- if let data = self.dragTempFilePath {
- if (self.limit) {
- // let _ = KMTools.saveWatermarkDocument(document: document!, to: URL(fileURLWithPath: data))
- } else {
- document?.write(to: URL(fileURLWithPath: data))
- }
- }
- self.dragFilePath = self.dragTempFilePath
- }
- return super.collectionView(collectionView, draggingSession: session, willBeginAt: screenPoint, forItemsAt: indexes)
- }
-
- override func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {
- if self.isNeedMarkerLine {
- KMPrint(collectionView)
- // if self.markBeginIndexes.count != 0 {
- // if !self.markBeginIndexes.contains(proposedDropIndexPath.pointee.item) {
- //标记线
- // if collectionView == self.collectionView {
- if (self.collectionView.item(at: proposedDropIndexPath.pointee.item) != nil) {
- var rect = self.collectionView.frameForItem(at: proposedDropIndexPath.pointee.item)
- // KMPrint("标记线范围 \(rect)")
- rect.size.height = 2
- self.markerLineView.frame = rect
- self.markerLineView.isHidden = false
- } else {
- let count = self.collectionView.numberOfItems(inSection: 0)
- if proposedDropIndexPath.pointee.item == count {
- var rect = self.collectionView.frameForItem(at: count - 1)
- // KMPrint("标记线范围 \(rect)")
- rect.origin.y += rect.size.height
- rect.size.height = 2
- self.markerLineView.frame = rect
- self.markerLineView.isHidden = false
- }
- }
- //// }
- //// }
- print(proposedDropIndexPath.pointee.item)
- // }
- }
- // debugPrint("移动中")
- if !KMThumbnailManager.manager.dragCollectionViews.contains(collectionView) {
- KMThumbnailManager.manager.dragCollectionViews.append(collectionView)
- }
- return super.collectionView(collectionView, validateDrop: draggingInfo, proposedIndexPath: proposedDropIndexPath, dropOperation: proposedDropOperation)
- }
-
- override func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {
- self.hiddenMarkerLineView()
- self.markBeginIndexes = IndexSet()
- self.dragIn = true
-
- let pboard = draggingInfo.draggingPasteboard
- if (pboard.availableType(from: [self.localForDraggedTypes]) != nil) {
- guard let dragIndexPath = self.dragedIndexPaths.first else {
- return false
- }
- guard let document = self.document else {
- return false
- }
- let dragIndex = dragIndexPath.item
- let toIndex = max(0, indexPath.item)
- if dragIndex < 0 || dragIndex > document.pageCount {
- return false
- }
- if (toIndex >= document.pageCount) {
- return false
- }
- if dragIndex == toIndex {
- return false
- }
- return super.collectionView(collectionView, acceptDrop: draggingInfo, indexPath: indexPath, dropOperation: dropOperation)
- } else if (pboard.availableType(from: [.localDraggedTypes]) != nil) {
- if let data = draggingInfo.draggingSource as? NSCollectionView, data.isEqual(to: collectionView) {
- // Swift.debugPrint("当前文件拖拽")
- return super.collectionView(collectionView, acceptDrop: draggingInfo, indexPath: indexPath, dropOperation: dropOperation)
- } else {
- // Swift.debugPrint("不同文件拖拽")
- if let _urlString = self.dragTempFilePath {
- self.delegate?.thumbnailView?(thumbanView: self, didDragAddFiles: [URL(fileURLWithPath: _urlString)], indexpath: indexPath)
- }
- }
- } else if ((pboard.availableType(from: [.fileURL])) != nil) {
- if let should = self.delegate?.thumbnailView?(thumbanView: self, shouldAcceptDrop: draggingInfo, indexPath: indexPath, dropOperation: dropOperation), !should {
- return should
- }
-
- guard let pbItems = pboard.pasteboardItems else {
- return false
- }
-
- //获取url
- var array: [URL] = []
- for item in pbItems {
- guard let data = item.string(forType: .fileURL), let _url = URL(string: data) else {
- continue
- }
- let type = _url.pathExtension.lowercased()
- if let _allowedFileTypes = self.kmAllowedFileTypes {
- if (_allowedFileTypes.contains(type)) {
- array.append(_url)
- }
- } else {
- array.append(_url)
- }
- }
-
- self.delegate?.thumbnailView?(thumbanView: self, didDragAddFiles: array, indexpath: indexPath)
- }
-
- return false
- }
-
- func collectionView(_ collectionView: NSCollectionView,
- pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {
- if let can = self.delegate?.thumbnailView?(thumbanView: self, canPasteboardWriterForItemAt: indexPath), !can {
- return nil
- }
-
- if let provider = self.delegate?.thumbnailView?(thumbanView: self, pasteboardWriterForItemAt: indexPath) {
- return provider
- }
-
- var provider: NSFilePromiseProvider?
- // 创建数据提供者
- let fileExtension = "pdf"
- if #available(macOS 11.0, *) {
- if let typeIdentifier = UTType(filenameExtension: fileExtension) {
- provider = KMFilePromiseProvider(fileType: typeIdentifier.identifier, delegate: self)
- }
- } else {
- if let typeIdentifier =
- UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension as CFString, nil) {
- provider = KMFilePromiseProvider(fileType: typeIdentifier.takeRetainedValue() as String, delegate: self)
- }
- }
-
- // 记录拖拽索引
- self.dragedIndexPaths.append(indexPath)
- do {
- if let _url = self.document?.documentURL {
- let data = try NSKeyedArchiver.archivedData(withRootObject: indexPath, requiringSecureCoding: false)
- provider?.userInfo = [KMFilePromiseProvider.UserInfoKeys.urlKey: _url,
- KMFilePromiseProvider.UserInfoKeys.indexPathKey: data]
- } else {
- let data = try NSKeyedArchiver.archivedData(withRootObject: indexPath, requiringSecureCoding: false)
- provider?.userInfo = [KMFilePromiseProvider.UserInfoKeys.indexPathKey: data]
- }
- } catch {
- fatalError("failed to archive indexPath to pasteboard")
- }
- return provider
- }
-
- override func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, dragOperation operation: NSDragOperation) {
- // if let _ = session.draggingPasteboard.availableType(from: [.localDraggedTypes]) {
- // Swift.debugPrint("本地拖拽")
- // } else {
- if (!self.dragIn) {
- var indexpaths = Set<IndexPath>()
- for indexpath in self.dragedIndexPaths {
- indexpaths.insert(indexpath)
- }
- // 清空数据
- self.dragedIndexPaths.removeAll()
- // 刷新数据
- self.reloadData()
- // 重新选中数据
- self.selectionIndexPaths = indexpaths
- } else {
- Swift.debugPrint("拖入文件 或 本地拖拽")
- }
- self.dragIn = false
-
- self.hiddenMarkerLineView()
- self.markBeginIndexes = IndexSet()
- // }
-
- super.collectionView(collectionView, draggingSession: session, endedAt: screenPoint, dragOperation: operation)
- }
- }
- extension KMPDFThumbnailView {
- func hiddenMarkerLineView() {
- for item in KMThumbnailManager.manager.dragCollectionViews {
- let view = item.superview?.superview?.superview as? KMPDFThumbnailView
- view?.markerLineView.isHidden = true
- }
- KMThumbnailManager.manager.dragCollectionViews.removeAll()
- }
- }
- // MARK: - KMExtensions
- extension KMPDFThumbnailView {
- var dragTempFloderPath: String? {
- get {
- return NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier ?? "").stringByAppendingPathComponent("KMPDFThumbnailView_Drag_Temp")
- }
- }
- var dragTempFilePath: String? {
- get {
- return self.dragTempFloderPath?.stringByAppendingPathComponent("drag_tmp.pdf")
- }
- }
- }
- // MARK: - NSFilePromiseProviderDelegate
- extension KMPDFThumbnailView: NSFilePromiseProviderDelegate {
- func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider, fileNameForType fileType: String) -> String {
- var fileName: String = "Untitle"
- if let _string = self.document?.documentURL.deletingPathExtension().lastPathComponent {
- fileName = _string
- }
- fileName.append(" pages")
- var indexs = IndexSet()
- for indexpath in self.dragedIndexPaths {
- indexs.insert(indexpath.item)
- }
- fileName.append(" ")
- fileName.append(KMPageRangeTools.newParseSelectedIndexs(selectedIndex: indexs.sorted()))
- fileName.append(".pdf")
-
- return fileName
- }
-
- func filePromiseProvider(_ filePromiseProvider: NSFilePromiseProvider,
- writePromiseTo url: URL,
- completionHandler: @escaping (Error?) -> Void) {
- do {
- /** Copy the file to the location provided to you. You always do a copy, not a move.
- It's important you call the completion handler.
- */
- if let _urlString = self.dragFilePath, !self.dragFlag {
- self.dragFlag = true
- if let should = self.delegate?.thumbnailView?(thumbanView: self, shouldPasteboardWriterForItemAt: IndexPath(item: 0, section: 0)), !should {
- completionHandler(nil)
- return
- }
-
- try FileManager.default.copyItem(at: URL(fileURLWithPath: _urlString), to: url)
- }
-
- completionHandler(nil)
- } catch let error {
- OperationQueue.main.addOperation {
- if let win = self.window {
- self.presentError(error, modalFor: win,
- delegate: nil, didPresent: nil, contextInfo: nil)
- }
- }
- completionHandler(error)
- }
- }
-
- /** You should provide a non main operation queue (e.g. one you create) via this function.
- This way you don't stall the main thread while writing the promise file.
- */
- func operationQueue(for filePromiseProvider: NSFilePromiseProvider) -> OperationQueue {
- return self.filePromiseQueue
- }
-
- // Utility function to return a PhotoItem object from the NSFilePromiseProvider.
- // func photoFromFilePromiserProvider(filePromiseProvider: NSFilePromiseProvider) -> CPDFPage? {
- // var result: CPDFPage?
- // if let userInfo = filePromiseProvider.userInfo as? [String: AnyObject] {
- // do {
- // if let indexPathData = userInfo[KMFilePromiseProvider.UserInfoKeys.indexPathKey] as? Data {
- // if let indexPath =
- // try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(indexPathData) as? IndexPath {
- // result = self.document?.page(at: UInt(indexPath.item))
- // }
- // }
- // } catch {
- // fatalError("failed to unarchive indexPath from promise provider.")
- // }
- // }
- // return result
- // }
- }
|