123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- //
- // KMNBotaAnnotationHanddler.swift
- // PDF Reader Pro
- //
- // Created by User-Tangchao on 2024/12/6.
- //
- import Cocoa
- @objc enum KMNBotaAnnotationSortType: Int {
- case page = 0
- case time = 1
- }
- @objc protocol KMNBotaAnnotationHanddlerDelegate: NSObjectProtocol {
- @objc optional func dataDidInit(handdle: KMNBotaAnnotationHanddler, datas: [KMNBotaAnnotationSectionModel]?)
- }
- @objcMembers class KMNBotaAnnotationHanddler: NSObject {
- weak var pdfView: CPDFView?
-
- weak var delegate: KMNBotaAnnotationHanddlerDelegate?
-
- var pdfDocument: CPDFDocument? {
- get {
- return pdfView?.document
- }
- }
-
- // 按页面排序
- var sortType: KMNBotaAnnotationSortType = .page {
- didSet {
- reloadAnnottionDatas()
- }
- }
- // 按升序排序
- var sortSubType: KMSortMode = .ascending {
- didSet {
- reloadAnnottionDatas()
- }
- }
-
- var datas: [KMNBotaAnnotationSectionModel] = [] //实际展示的数据
-
- var allOrgDatas: [KMNBotaAnnotationModel] = [] //所有显示的数据
-
- func defaultallTypes() -> [String] {
- return [CPDFAnnotation.kType.highlight,
- CPDFAnnotation.kType.underline,
- CPDFAnnotation.kType.strikeout,
- CPDFAnnotation.kType.squiggly,
- CPDFAnnotation.kType.freehand,
- CPDFAnnotation.kType.freetext,
- CPDFAnnotation.kType.note,
- CPDFAnnotation.kType.square,
- CPDFAnnotation.kType.circle,
- CPDFAnnotation.kType.line,
- CPDFAnnotation.kType.arrow,
- CPDFAnnotation.kType.stamp,
- CPDFAnnotation.kType.image,
- CPDFAnnotation.kType.sign,
- CPDFAnnotation.kType.redact,
- CPDFAnnotation.kType.polyline,
- CPDFAnnotation.kType.polygon]
- }
-
-
- func reloadOrgAllAnnottionDatas(){
- allOrgDatas = []
- enumerateAllPages { page, stop in
- // 根据注释 Type 过滤
- let filterNotes = getFilterNotes(types: defaultallTypes(), for: page)
- if filterNotes.isEmpty {
- return
- }
- for note in filterNotes {
- if note.annotationShouldDisplay() == false { // 注释已隐藏
- continue
- }
- let model = KMNBotaAnnotationModel()
- model.annotation = note
- allOrgDatas.append(model)
- }
- }
- }
- func reloadAnnottionDatas(){
- var showDatas:[KMNBotaAnnotationSectionModel] = []
- if sortType == .page {
- var sortedOrgDatas:[KMNBotaAnnotationModel] = []
- if sortSubType == .ascending {
- sortedOrgDatas = allOrgDatas.sorted { $0.annotation?.pageIndex() ?? 0 < $1.annotation?.pageIndex() ?? 0 }
- } else {
- sortedOrgDatas = allOrgDatas.sorted { $0.annotation?.pageIndex() ?? 0 > $1.annotation?.pageIndex() ?? 0 }
- }
- for annotationModel in sortedOrgDatas {
- var isNeedAdd = true
- for sectionModel in showDatas {
- if let item = sectionModel.items.first {
- if(item.annotation?.pageIndex() == annotationModel.annotation?.pageIndex()) {
- sectionModel.items.append(annotationModel)
- isNeedAdd = false
- break
- }
- }
- }
- if isNeedAdd == false {
- let sectionModel = KMNBotaAnnotationSectionModel()
- sectionModel.items.append(annotationModel)
- showDatas.append(sectionModel)
- }
- }
- } else if sortType == .time {
- var sortedOrgDatas:[KMNBotaAnnotationModel] = []
- if sortSubType == .ascending {
- let sortedOrgDatas = allOrgDatas.sorted { $0.annotationDate.timeIntervalSince1970 < $1.annotationDate.timeIntervalSince1970 }
- } else {
- let sortedOrgDatas = allOrgDatas.sorted { $0.annotationDate.timeIntervalSince1970 > $1.annotationDate.timeIntervalSince1970 }
- }
- for annotationModel in sortedOrgDatas {
- var isNeedAdd = true
- for sectionModel in showDatas {
- if let item = sectionModel.items.first {
- let theDate = item.annotation?.modificationDate()
- let newDate = annotationModel.annotation?.modificationDate()
- if (theDate != nil) {
- if theDate!.isSameDay(other: newDate) {
- sectionModel.items.append(annotationModel)
- isNeedAdd = false
- break
- }
- }
- }
- }
- if isNeedAdd == true {
- let sectionModel = KMNBotaAnnotationSectionModel()
- sectionModel.items.append(annotationModel)
- showDatas.append(sectionModel)
- }
- }
- }
- datas = showDatas
- delegate?.dataDidInit?(handdle: self, datas: datas)
- }
-
- // 获取 Page 的 注释列表 【根据 Types】
-
- func getFilterNotes(types: [String], for page: CPDFPage) -> [CPDFAnnotation] {
- let notes = page.annotations ?? []
- let filterNotes = Self.filterAnnotation(annotations: notes, types: types)
- return filterNotes as? [CPDFAnnotation] ?? []
- }
-
- // 遍历 所有 Section 试图模型 【二分法 遍历】
-
- /*
- orderedAscending: 左操作数小于右操作数
- orderedDescending: 左操作数大于右操作数
- orderedSame: 左右操作数相等
- */
-
- func enumeratedAllSectionViewModel(callback: ((_ viewModel: KMNBotaAnnotationSectionModel?, _ stop: inout Bool, _ result: inout ComparisonResult)->Void)) {
- var lowerBound = 0
- var upperBound = datas.count
-
- var stop = false
- var result: ComparisonResult = .orderedSame
- while lowerBound < upperBound {
- let midIndex = lowerBound + (upperBound - lowerBound) / 2
-
- callback(datas[midIndex], &stop, &result)
- if stop || result == .orderedSame { // 找到
- break
- }
-
- if result == .orderedAscending { // 左操作数小于右操作数 则在 下半区查找
- lowerBound = midIndex + 1
- } else {
- upperBound = midIndex
- }
- }
- return callback(nil, &stop, &result)
- }
-
- // 获取所有 Page
-
- func enumerateAllPages(callback: ((_ page: CPDFPage, _ stop: inout Bool)->Void)) {
- let count = pdfDocument?.pageCount ?? 0
- for i in 0 ..< count {
- guard let page = pdfDocument?.page(at: i) else {
- continue
- }
-
- var stop = false
- callback(page, &stop)
- if stop {
- break
- }
- }
- }
-
- class func filterAnnotation(annotations: [Any], types: [Any]) -> [Any] {
- let array = annotations
- let leftExpression = NSExpression(forKeyPath: "type")
- let rightExpression = NSExpression(forConstantValue: types)
- let predicate = NSComparisonPredicate(
- leftExpression: leftExpression,
- rightExpression: rightExpression,
- modifier: .direct,
- type: .in,
- options: .diacriticInsensitive
- )
- return (array as NSArray).filtered(using: predicate)
- }
- }
|