// // KMLeftSideViewController+Thumbnail.swift // PDF Master // // Created by tangchao on 2024/1/12. // import Foundation extension KMLeftSideViewController.Key { static let thumbSizeScaling = "KMThumbnailSizeScalingKey" } // MARK: - Actions extension KMLeftSideViewController { public func refreshUIOfThumbnailIfNeed(preference: Bool = false) { if self.type.methodType != .Thumbnail { return } if preference { self.reloadThumbnailSize() } Task { @MainActor in self.thumbnailTableView.reloadData() } } public func reloadThumbnailDataIfNeed() { if self.type.methodType != .Thumbnail { return } self.resetThumbnails() } public func reloadThumbnailSize() { let defaultSize = roundf(KMPreference.shared.thumbPageSize) // var thumbnailSize = (defaultSize < TINY_SIZE + FUDGE_SIZE) ? TINY_SIZE : (defaultSize < SMALL_SIZE + FUDGE_SIZE) ? SMALL_SIZE : (defaultSize < LARGE_SIZE + FUDGE_SIZE) ? LARGE_SIZE : HUGE_SIZE var thumbnailSize = TINY_SIZE if defaultSize < TINY_SIZE + FUDGE_SIZE { } else { if defaultSize < SMALL_SIZE + FUDGE_SIZE { thumbnailSize = SMALL_SIZE } else { if defaultSize < LARGE_SIZE + FUDGE_SIZE { thumbnailSize = LARGE_SIZE } else { thumbnailSize = HUGE_SIZE } } } if (abs(thumbnailSize - Float(self.thumbnailCacheSize)) > FUDGE_SIZE) { self.thumbnailCacheSize = thumbnailSize.cgFloat } Task { @MainActor in self.thumbnailTableView.reloadData() } } // 显示缩略图模块 func showThumbnail() { if self.leftView.segmentedControl.selectedSegment == 0 { } else { self.leftView.segmentedControl.selectedSegment = 0 } } func updateThumbnail(at index: Int) { if index < self.thumbnails.count { self.thumbnails[index].dirty = true /* 原问题:CrashKit - SKMainWindowController updateThumbnailAtPageIndex:] ([__NSArrayM objectAtIndex:]: index 9223372036854775807 beyond bounds [0 .. 17]) 注释原因:缩略图高亮为自定义后,刷新会将高亮刷新到0行 */ // [leftSideController.thumbnailTableView reloadData]; // BOOL visible = NO; // PDFPage *page = [[pdfView document] pageAtIndex:anIndex]; // if([self.pdfView.visiblePages containsObject:page]) { // visible = YES; // } // NSInteger curIndex = [pdfView.document indexForPage:pdfView.currentPage]; // if (need && curIndex != anIndex && !visible) { // [pdfView goToPage:[[pdfView document] pageAtIndex:anIndex]]; // } } } func allThumbnailsNeedUpdate() { for thumb in self.thumbnails { thumb.dirty = true } self.reloadThumbnailSize() } func thumb_selectRowIndexsIfNeed(_ indexs: IndexSet) { if self.type.methodType != .Thumbnail { return } if indexs.isEmpty { return } Task { @MainActor in self.thumbnailTableView.selectRowIndexes(indexs, byExtendingSelection: false) self.thumbnailTableView.scrollRowToVisible(indexs.first ?? 0) } } func thumb_initSubViews() { self.thumbnailZoomInButton.target = self self.thumbnailZoomInButton.action = #selector(thumbnailSizeScaling) self.thumbnailZoomInButton.tag = 1 self.thumbnailZoomOutButton.target = self self.thumbnailZoomOutButton.action = #selector(thumbnailSizeScaling) self.thumbnailZoomOutButton.tag = 0 self.thumbnailTableView.delegate = self self.thumbnailTableView.dataSource = self self.thumbnailTableView.thumbDelegate = self self.thumbnailTableView.botaDelegate = self self.thumbnailTableView.menu?.delegate = self // [thumbnailTableView registerForDraggedTypes:@[KPDFThumbnailLocalForDraggedTypes,NSFilenamesPboardType]]; self.thumbnailTableView.registerForDraggedTypes([.localDraggedTypes, .fileURL,.string,.pdf]) self.thumbnailTableView.setDraggingSourceOperationMask(.every, forLocal: false) } func thumb_initDefalutValue() { self.thumbnailView.wantsLayer = true self.thumbnailView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.thumbnailTitleLabel.stringValue = KMLocalizedString("Thumbnails", nil) self.thumbnailTitleLabel.textColor = KMAppearance.Layout.h0Color() self.thumbnailZoomInButton.toolTip = KMLocalizedString("Zoom In", nil) self.thumbnailZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil) self.thumbnailTableView.backgroundColor = KMAppearance.Layout.l0Color() self.thumbnailTableView.allowsMultipleSelection = true self.thumbnailTableView.selectionHighlightStyle = .none } } // MARK: - Others extension KMLeftSideViewController {} // MARK: - KMThumbnailTableViewDelegate extension KMLeftSideViewController: KMThumbnailTableViewDelegate { func tableView(_ tableView: NSTableView, highlightLevelForRow row: Int) -> UInt { if tableView.isEqual(to: self.thumbnailTableView) { // NSUInteger i, iMax = [lastViewedPages count]; // for (i = 0; i < iMax; i++) { // if (row == (NSInteger)[lastViewedPages pointerAtIndex:i]) // return i; // } } return UInt.max } func tableView(_ tableView: NSTableView, commandSelectRow rowIndex: Int) -> Bool { if tableView.isEqual(to: self.thumbnailTableView) { // NSRect rect = [[[pdfView document] pageAtIndex:row] boundsForBox:kPDFDisplayBoxCropBox]; // // rect.origin.y = NSMidY(rect) - 0.5 * SNAPSHOT_HEIGHT; // rect.size.height = SNAPSHOT_HEIGHT; // [self showSnapshotAtPageNumber:row forRect:rect scaleFactor:[pdfView scaleFactor] autoFits:NO]; let thumbailTabCell = tableView.view(atColumn: 0, row: rowIndex, makeIfNecessary: true) as? KMThumbnailTableviewCell thumbailTabCell?.isSelectCell = true var rowIndexSet = IndexSet() for i in self.thumbnailTableView.selectedRowIndexes { rowIndexSet.insert(i) } rowIndexSet.insert(rowIndex) self.thumbnailTableView.selectRowIndexes(rowIndexSet, byExtendingSelection: true) return true } return false } func tableView(_ tableView: NSTableView, shiftSelectRow rowIndex: Int) -> Bool { if tableView.isEqual(to: self.thumbnailTableView) { if (self.thumbnailTableView.selectedRowIndexes.count == 0) { let thumbailTabCell = tableView.view(atColumn: 0, row: rowIndex, makeIfNecessary: true) as? KMThumbnailTableviewCell thumbailTabCell?.isSelectCell = true var rowIndexSet = IndexSet() self.thumbnailTableView.selectRowIndexes(rowIndexSet, byExtendingSelection: true) return true } else if (self.thumbnailTableView.selectedRowIndexes.count == 1 && self.thumbnailTableView.selectedRowIndexes.first == rowIndex) { return false } else { var fristIndex = self.thumbnailTableView.selectedRowIndexes.first ?? Int.min var lastIndex = self.thumbnailTableView.selectedRowIndexes.last ?? Int.max for idx in self.thumbnailTableView.selectedRowIndexes { // [leftSideController.thumbnailTableView.selectedRowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { if(idx < fristIndex) { fristIndex = idx } if(idx > lastIndex) { lastIndex = idx } } if(rowIndex < fristIndex) { fristIndex = rowIndex } else if (rowIndex > lastIndex) { lastIndex = rowIndex } var rowIndexSet = IndexSet() for i in fristIndex ... lastIndex { rowIndexSet.insert(i) } self.thumbnailTableView.selectRowIndexes(rowIndexSet, byExtendingSelection: true) return true } } return false } } // MARK: - Undo & Redo extension KMLeftSideViewController { @objc dynamic func tableView(_ tv: NSTableView, rotateRowsWithIndexes rowIndexes: NSIndexSet) { if tv.isEqual(to: self.thumbnailTableView) { for idx in rowIndexes { if (idx != NSNotFound) { let page = self.listView.document.page(at: UInt(idx)) (self.listView.undoManager?.prepare(withInvocationTarget: self) as AnyObject).rotatePage(page, pageAt: idx) page?.rightRotate() self.listView.layoutDocumentView() self.resetThumbnails() // NSInteger pageIndex = MIN(idx, [[pdfView document] pageCount]-1); // [pdfView goToPage:[[pdfView document] pageAtIndex:pageIndex]]; } self.thumbnailTableView.selectRowIndexes(rowIndexes as IndexSet, byExtendingSelection: true) } } } @objc dynamic func rotatePage(_ page: CPDFPage?, pageAt index: Int) { (self.listView.undoManager?.prepare(withInvocationTarget: self) as AnyObject).tableView(self.thumbnailTableView, rotateRowsWithIndexes: NSIndexSet(index: index)) page?.leftRotate() self.listView.layoutDocumentView() self.resetThumbnails() } @objc dynamic func insertPage(_ page: CPDFPage, pageAt index: Int) { (self.listView.undoManager?.prepare(withInvocationTarget: self) as AnyObject).tableView(self.thumbnailTableView, deleteRowsWithIndexes: IndexSet(integer: index)) self.listView.document.insertPageObject(page, at: UInt(index)) self.listView.layoutDocumentView() // [pageLabels setArray:[[pdfView document] pageLabels]]; self.resetThumbnails() let pageIndex = min(index, Int((self.listView.document?.pageCount ?? 0))-1) self.listView.go(toPageIndex: pageIndex, animated: false) } @objc dynamic func insertPages(_ selectedIndexSet: IndexSet, pageAt index: Int) { (self.listView.undoManager?.prepare(withInvocationTarget: self) as AnyObject).deletePages(selectedIndexSet, pageAt: index) self.listView.layoutDocumentView() // [pageLabels setArray:[[pdfView document] pageLabels]]; self.resetThumbnails() if let pageIndex = selectedIndexSet.first { self.listView.go(toPageIndex: pageIndex, animated: false) } } @objc dynamic func deletePages(_ selectedIndexSet: IndexSet, pageAt index: Int) { (self.listView.undoManager?.prepare(withInvocationTarget: self) as AnyObject).insertPages(selectedIndexSet, pageAt: index) for idx in selectedIndexSet { if idx < self.listView.document.pageCount { self.listView.document.removePage(at: UInt(idx)) } } self.listView.layoutDocumentView() // [pageLabels setArray:[[pdfView document] pageLabels]]; self.resetThumbnails() let pageIndex = min(index, Int(self.listView.document.pageCount)-1) self.listView.go(toPageIndex: pageIndex, animated: false) } }