// // KMTableView.swift // PDF Reader Pro // // Created by tangchao on 2023/11/16. // import Cocoa /* @protocol SKTableViewDelegate - (NSArray *)tableView:(NSTableView *)aTableView typeSelectHelperSelectionStrings:(SKTypeSelectHelper *)aTypeSelectHelper; - (void)tableView:(NSTableView *)aTableView typeSelectHelper:(SKTypeSelectHelper *)aTypeSelectHelper didFailToFindMatchForSearchString:(NSString *)searchString; - (void)tableView:(NSTableView *)aTableView typeSelectHelper:(SKTypeSelectHelper *)aTypeSelectHelper updateSearchString:(NSString *)searchString; @end */ @objc protocol KMBotaTableViewDelegate: NSTableViewDelegate { @objc optional func tableView(_ aTableView: NSTableView, deleteRowsWithIndexes rowIndexes: IndexSet) @objc optional func tableView(_ aTableView: NSTableView, canDeleteRowsWithIndexes rowIndexes: IndexSet) -> Bool @objc optional func tableView(_ aTableView: NSTableView, copyRowsWithIndexes rowIndexes: IndexSet) @objc optional func tableView(_ aTableView: NSTableView, canCopyRowsWithIndexes rowIndexes: IndexSet) -> Bool @objc optional func tableView(_ aTableView: NSTableView, pasteFromPasteboard pboard: NSPasteboard) @objc optional func tableView(_ aTableView: NSTableView, canPasteFromPasteboard pboard: NSPasteboard) -> Bool @objc optional func tableViewMoveLeft(_ aTableView: NSTableView) @objc optional func tableViewMoveRight(_ aTableView: NSTableView) @objc optional func tableView(_ aTableView: NSTableView, imageContextForRow rowIndex: Int) -> AnyObject? } class KMBotaTableView: NSTableView { var kmTrackingAreas: NSMutableSet? /* @interface SKTableView : NSTableView { SKTypeSelectHelper *typeSelectHelper; } @property (nonatomic) supportsQuickLook; @property (nonatomic, retain) SKTypeSelectHelper *typeSelectHelper; */ weak var botaDelegate: KMBotaTableViewDelegate? { didSet { self._rebuildTrackingAreas() } } var hasImageToolTips: Bool { get { return self.kmTrackingAreas != nil } set { if self.kmTrackingAreas == nil && newValue { self.kmTrackingAreas = NSMutableSet() if self.window != nil { self._rebuildTrackingAreas() } } else if self.kmTrackingAreas != nil && newValue == false { if self.window != nil { self._removeTrackingAreas() } } } } override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) // Drawing code here. } override func reloadData() { super.reloadData() self._rebuildTrackingAreas() // [typeSelectHelper rebuildTypeSelectSearchCache]; } // MARK: - Tracking override func updateTrackingAreas() { super.updateTrackingAreas() self._rebuildTrackingAreas() } override func noteNumberOfRowsChanged() { super.noteNumberOfRowsChanged() self._rebuildTrackingAreas() } override func mouseEntered(with event: NSEvent) { if (self.kmTrackingAreas == nil) { return } // let userInfo = event.userData as? [String : Any] let userInfo = event.trackingArea?.userInfo as? [String : Any] let row = userInfo?["row"] as? Int if row != nil { let context = self.botaDelegate?.tableView?(self, imageContextForRow: row!) if context is KMImageToolTipContext { KMImageToolTipWindow.shared.showForImageContext(context as! KMImageToolTipContext, at: .zero) } } } override func mouseExited(with event: NSEvent) { if (self.kmTrackingAreas == nil) { return } let userInfo = event.userData as? [String : Any] let row = userInfo?["row"] as? Int if row != nil { KMImageToolTipWindow.shared.fadeOut() } } func scrollToBeginningOfDocument(_ sender: AnyObject?) { if self.numberOfRows > 0 { self.scrollRowToVisible(0) } } func scrollToEndOfDocument(_ sender: AnyObject?) { if self.numberOfRows > 0 { self.scrollRowToVisible(self.numberOfRows-1) } } func moveLeft(_ sender: AnyObject?) { self.botaDelegate?.tableViewMoveLeft?(self) } func moveRight(_ sender: AnyObject?) { self.botaDelegate?.tableViewMoveRight?(self) } func canDelete() -> Bool { let indexes = self.selectedRowIndexes if indexes.isEmpty { return false } return self.botaDelegate?.tableView?(self, canDeleteRowsWithIndexes: indexes) ?? false } @objc func delete(_ sender: AnyObject?) { if self.canDelete() { self.botaDelegate?.tableView?(self, deleteRowsWithIndexes: self.selectedRowIndexes) } } func canCopy() -> Bool { let indexes = self.selectedRowIndexes if indexes.isEmpty { return false } return self.botaDelegate?.tableView?(self, canCopyRowsWithIndexes: indexes) ?? false } @objc func copy(_ sender: AnyObject?) { if self.canCopy() { self.botaDelegate?.tableView?(self, copyRowsWithIndexes: self.selectedRowIndexes) } } func canPaste() -> Bool { return self.botaDelegate?.tableView?(self, canPasteFromPasteboard: NSPasteboard.general) ?? false } @objc func paste(_ sender: AnyObject?) { if self.canPaste() { self.botaDelegate?.tableView?(self, pasteFromPasteboard: NSPasteboard.general) } } override func keyDown(with event: NSEvent) { // let eventChar = event.PDFListViewFirstCharacter() // let modifierFlags = event.deviceIndependen // NSUInteger modifierFlags = [theEvent deviceIndependentModifierFlags]; // // if ((eventChar == NSNewlineCharacter || eventChar == NSEnterCharacter || eventChar == NSCarriageReturnCharacter) && modifierFlags == 0) { // if ([self doubleAction] == NULL || [self sendAction:[self doubleAction] to:[self target]] == NO) // NSBeep(); // } else if ((eventChar == NSDeleteCharacter || eventChar == NSDeleteFunctionKey) && modifierFlags == 0 && [self canDelete]) { // [self delete:self]; // } else if ((eventChar == SKSpaceCharacter) && modifierFlags == 0) { // if (supportsQuickLook == NO) // [[self enclosingScrollView] pageDown:nil]; // else if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]) // [[QLPreviewPanel sharedPreviewPanel] orderOut:nil]; // else // [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil]; // } else if ((eventChar == SKSpaceCharacter) && modifierFlags == NSShiftKeyMask) { // if (supportsQuickLook == NO) // [[self enclosingScrollView] pageUp:nil]; // } else if (eventChar == NSHomeFunctionKey && (modifierFlags & ~NSFunctionKeyMask) == 0) { // [self scrollToBeginningOfDocument:nil]; // } else if (eventChar == NSEndFunctionKey && (modifierFlags & ~NSFunctionKeyMask) == 0) { // [self scrollToEndOfDocument:nil]; // } else if (eventChar == NSLeftArrowFunctionKey && modifierFlags == 0) { // [self moveLeft:nil]; // } else if (eventChar == NSRightArrowFunctionKey && modifierFlags == 0) { // [self moveRight:nil]; // } else if ([typeSelectHelper handleEvent:theEvent] == NO) { // [super keyDown:theEvent]; // } super.keyDown(with: event) } override var font: NSFont? { get { for tc in self.tableColumns { if let cell = tc.dataCell as? NSCell { if cell.type == .textCellType { return cell.font } } } return nil } set { for tc in self.tableColumns { if let cell = tc.dataCell as? NSCell { if cell.type == .textCellType { cell.font = newValue } } } var rowHeight = font?.defaultViewLineHeight() ?? 34 if self.selectionHighlightStyle == .sourceList { rowHeight += 2.0 } self.rowHeight = rowHeight self.noteHeightOfRows(withIndexesChanged: IndexSet(0.. Bool { if menuItem.action == #selector(delete) { return self.canDelete() } else if menuItem.action == KMSelectorCopy { return self.canCopy() } else if menuItem.action == #selector(paste) { return self.canPaste() } else if menuItem.action == #selector(selectAll) { return self.allowsMultipleSelection } else if menuItem.action == #selector(deselectAll) { return self.allowsEmptySelection } // else if ([[SKTableView superclass] instancesRespondToSelector:@selector(validateMenuItem:)]) // return [super validateMenuItem:menuItem]; return true } }