// // KMLeftSideViewController.swift // PDF Master // // Created by lxy on 2022/10/10. // import Cocoa @objc protocol KMLeftSideViewControllerDelegate { @objc optional func controlStateChange(_ obj: KMLeftSideViewController,show:Bool) @objc optional func enterEditMode(_ obj: KMLeftSideViewController, _ pages: [Int]) @objc optional func searchAction(searchString:String, isCase:Bool) @objc optional func controller(_ controller: KMLeftSideViewController, dispayDidChange dispay: KMPDFDisplayType) @objc optional func controller(controller: KMLeftSideViewController, itemClick item: Any?, itemKey: KMItemKey, params: Any?) @objc optional func controller(controller: KMLeftSideViewController, bookMarkDidChange bookMarks: [KMBookMarkItem]) @objc optional func controller(controller: KMLeftSideViewController, rotateType: KMRotateType) } class KMLeftSideViewController: KMSideViewController { var dataSource : [KMLeftMethodMode] = [KMLeftMethodMode]() var type : KMLeftMethodMode = KMLeftMethodMode() var isShowPanel : Bool = false var norImage : [String] = [] var selectImage : [String] = [] var mainVC: KMMainViewController? var selectPages: [Int]? open weak var delegate: KMLeftSideViewControllerDelegate? deinit { KMPrint("KMLeftSideViewController deinit.") NotificationCenter.default.removeObserver(self) } override var nibName: NSNib.Name? { return "LeftSideView" } convenience init(type : KMLeftMethodMode) { self.init() self.type = type } override func viewDidLoad() { super.viewDidLoad() DistributedNotificationCenter.default().addObserver(self, selector: #selector(_themeChanged), name: NSApplication.interfaceThemeChangedNotification, object: nil) } func showPanelView(show: Bool) { self.isShowPanel = show if show { self.leftView.segmentedControl.selectedSegment = 0 } else { self.leftView.segmentedControl.selectedSegment = UInt8.max self.delegate?.controlStateChange?(self, show: false) } } func refreshMethodType(methodType: BotaType) { let newType = KMLeftMethodMode() var show = true if self.type.methodType != methodType { newType.methodType = methodType } if self.type.methodType == methodType { show = false } else if methodType == .None { show = false } self.type = newType; self.delegate?.controlStateChange?(self,show:show) } // MARK: - New /* NSArrayController *findArrayController; NSArrayController *groupedFindArrayController; } - (void)applySearchTableHeader:(NSString *)message; */ @IBOutlet var segmentedControl: KMSegmentedControl! @IBOutlet var thumbnailTableView: KMThumbnailTableView! @IBOutlet var tocOutlineView: KMTocOutlineView! @IBOutlet var noteOutlineView: KMNoteOutlineView! @IBOutlet var findTableView: KMBotaTableView! @IBOutlet var groupedFindTableView: KMBotaTableView! @IBOutlet var snapshotTableView: KMBotaTableView! @IBOutlet weak var leftListView: NSView! @IBOutlet var searchViewController: KMBotaSearchViewController! @IBOutlet weak var toolButtonBox: NSBox! @IBOutlet weak var toolButtonBoxLayoutConstraint: NSLayoutConstraint! @IBOutlet weak var snapshotNormalView: NSView! @IBOutlet weak var snapshotLabel: NSTextField! @IBOutlet weak var snapshotNormalMoreButton: NSButton! @IBOutlet weak var snapshotNormalSearchButton: NSButton! @IBOutlet weak var snapshotNormalZoomOutButton: NSButton! @IBOutlet weak var snapshotNormalZoomInButton: NSButton! @IBOutlet weak var snapshotSearchZoomOutButton: NSButton! @IBOutlet weak var snapshotSearchZoomInButton: NSButton! @IBOutlet weak var snapshotSearchField: KMLeftSideViewSearchField! @IBOutlet weak var snapshotDoneButton: NSButton! @IBOutlet weak var outlineView: NSView! @IBOutlet weak var outlineMoreButton: NSButton! @IBOutlet weak var outlineAddButton: NSButton! @IBOutlet weak var outlineSearchButton: NSButton! @IBOutlet weak var outlineLabel: NSTextField! @IBOutlet weak var outlineSearchField: KMLeftSideViewSearchField! @IBOutlet weak var outlineDoneButton: NSButton! @IBOutlet weak var noteView: NSView! @IBOutlet weak var noteMoreButton: NSButton! @IBOutlet weak var noteFilterButton: NSButton! @IBOutlet weak var noteSearchButton: NSButton! @IBOutlet weak var noteSearchField: KMLeftSideViewSearchField! @IBOutlet weak var noteTitleLabel: NSTextField! @IBOutlet weak var noteHeaderView: NSView! @IBOutlet weak var sortTypeBox: KMBox! @IBOutlet weak var sortTypeLabel: NSTextField! @IBOutlet weak var noteSortButton: NSButton! @IBOutlet weak var noteDoneButton: NSButton! @IBOutlet weak var thumbnailView: NSView! @IBOutlet weak var thumbnailZoomOutButton: NSButton! @IBOutlet weak var thumbnailZoomInButton: NSButton! @IBOutlet weak var thumbnailTitleLabel: NSTextField! @IBOutlet weak var emptySearchBox: NSBox! @IBOutlet weak var emptySearchLabel: NSTextField! var filterButtonLayer: NSView? var moreButtonLayer: KMButtonLayer? var thumbnails: [KMThumbnail] = [] var isDisplayPageSize = false var thumbnailCacheSize: CGFloat = 32 * 3 var findState: KMFindState = .content var searchResults : [KMSearchMode] = [] { didSet { self.updataLeftSideFindView() } } var groupSearchResults: [KMSearchMode] = [] var findPaneState: KMFindPaneState = .singular var isSearchOutlineMode = false var outlineIgnoreCaseFlag = false var noteTypeDict: [String : Any] = [:] private let MIN_SIDE_PANE_WIDTH: CGFloat = 270 private let LABEL_COLUMNID = "label" var foldType: KMFoldAllAnnotationType = .none private let KMLeftSideViewNoteSortTypeKey = "KMLeftSideViewNoteSortTypeKey" private let KMLeftSideViewAscendSortBoolKey = "KMLeftSideViewAscendSortBoolKey" private let SKDisableTableToolTipsKey = "SKDisableTableToolTips" var tocType: KMFoldType = .none var snapshots: [Any] = [] private var _noteSortType: KMNoteSortType = .none var noteSortType: KMNoteSortType { get { return self._noteSortType } set { self._noteSortType = newValue NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMAnnotationSortTypeKeyNotification"), object: self) } } var isAscendSort = false { didSet { NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMAnnotationSortTypeKeyNotification"), object: self) } } lazy var leftSideEmptyVC: KMLeftSideEmptyFileViewController = { let vc = KMLeftSideEmptyFileViewController(nibName: "KMLeftSideEmptyFileViewController", bundle: nil) vc.view.wantsLayer = true return vc }() var preThumbnailRow: Int = 0 var leftMargin: CGFloat = 0 lazy var leftView: KMBotaLeftView = { let view = KMBotaLeftView() return view }() private var _copysPages: [CPDFPage] = [] private var _annotations: [KMBOTAAnnotationSection] = [] private var _allAnnotations: [CPDFAnnotation] = [] private let kKMPDFViewOutlineDragDataType = "kKMPDFViewOutlineDragDataType" private let KPDFThumbnailDoucumentURLForDraggedTypes = "KPDFThumbnailDoucumentURLForDraggedTypes" private var allFoldNotes: [CPDFAnnotation] = [] override func loadView() { super.loadView() self.view.wantsLayer = true self.view.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.view.addSubview(self.leftView) self.leftView.frame = NSMakeRect(0, 0, 44, NSHeight(self.view.frame)) self.leftView.autoresizingMask = [.height] self.leftView.wantsLayer = true self.leftView.layer?.backgroundColor = .white self.outlineView.wantsLayer = true self.outlineView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.noteView.wantsLayer = true self.noteView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.thumbnailView.wantsLayer = true self.thumbnailView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.snapshotNormalView.wantsLayer = true self.snapshotNormalView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.tocOutlineView.backgroundColor = KMAppearance.Layout.l0Color() self.noteOutlineView.backgroundColor = KMAppearance.Layout.l0Color() self.findTableView.backgroundColor = KMAppearance.Layout.l0Color() self.groupedFindTableView.backgroundColor = KMAppearance.Layout.l0Color() self.snapshotTableView.backgroundColor = KMAppearance.Layout.l0Color() self.thumbnailTableView.backgroundColor = KMAppearance.Layout.l0Color() self.leftListView.wantsLayer = true self.leftListView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.emptySearchLabel.stringValue = KMLocalizedString("No Results",nil) self.emptySearchLabel.textColor = KMAppearance.Layout.h0Color() self.emptySearchBox.isHidden = true self.thumbnailTitleLabel.stringValue = KMLocalizedString("Thumbnails", nil) self.thumbnailTitleLabel.textColor = KMAppearance.Layout.h0Color() self.thumbnailZoomInButton.action = #selector(thumbnailSizeScaling) self.thumbnailZoomInButton.target = self self.thumbnailZoomInButton.tag = 1 self.thumbnailZoomOutButton.action = #selector(thumbnailSizeScaling) self.thumbnailZoomOutButton.target = self self.thumbnailZoomOutButton.tag = 0 self.snapshotTableView.delegate = self self.snapshotTableView.dataSource = self self.snapshotTableView.menu?.delegate = self self.snapshotTableView.doubleAction = #selector(toggleSelectedSnapshots) self.snapshotTableView.target = self self.snapshotTableView.backgroundColor = .clear // [snapshotTableView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:NO]; self.snapshotLabel.stringValue = KMLocalizedString("Snapshots", nil) self.snapshotLabel.textColor = KMAppearance.Layout.h0Color() self.snapshotNormalZoomInButton.action = #selector(thumbnailSizeScaling) self.snapshotNormalZoomInButton.target = self self.snapshotNormalZoomInButton.tag = 2 self.snapshotNormalZoomOutButton.action = #selector(thumbnailSizeScaling) self.snapshotNormalZoomOutButton.target = self self.snapshotNormalZoomOutButton.tag = 3 self.snapshotNormalSearchButton.toolTip = KMLocalizedString("Search", nil) self.snapshotNormalMoreButton.action = #selector(leftSideViewMoreButtonAction) self.snapshotNormalMoreButton.target = self self.snapshotNormalMoreButton.tag = 300 self.snapshotSearchZoomInButton.action = #selector(thumbnailSizeScaling) self.snapshotSearchZoomInButton.target = self self.snapshotSearchZoomInButton.tag = 2 self.snapshotSearchZoomOutButton.action = #selector(thumbnailSizeScaling) self.snapshotSearchZoomOutButton.target = self self.snapshotSearchZoomOutButton.tag = 3 self.snapshotDoneButton.title = KMLocalizedString("Done", nil) self.snapshotDoneButton.toolTip = KMLocalizedString("Done", nil) self.snapshotDoneButton.setTitleColor(KMAppearance.Layout.w0Color()) self.snapshotDoneButton.wantsLayer = true self.snapshotDoneButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor self.snapshotDoneButton.layer?.cornerRadius = 4.0 self.snapshotDoneButton.action = #selector(leftSideViewDoneButtonAction) self.snapshotDoneButton.target = self self.snapshotDoneButton.tag = 312 self.snapshotDoneButton.isHidden = true self.noteOutlineView.autoresizesOutlineColumn = false self.noteOutlineView.delegate = self self.noteOutlineView.dataSource = self self.noteOutlineView.botaDelegate = self self.noteOutlineView.botaDataSource = self self.noteOutlineView.noteDelegate = self self.noteOutlineView.menu = NSMenu() self.noteOutlineView.menu?.delegate = self // [noteOutlineView setTypeSelectHelper:[SKTypeSelectHelper typeSelectHelperWithMatchOption:SKSubstringMatch]]; self.noteOutlineView.indentationPerLevel = 0 // [noteOutlineView registerForDraggedTypes:[NSColor readableTypesForPasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]]]; self.noteOutlineView.target = self self.noteOutlineView.doubleAction = #selector(selectSelectedNote) self.tocOutlineView.menu = NSMenu() self.tocOutlineView.menu?.delegate = self self.outlineSearchField.delegate = self self.snapshotSearchField.backgroundColor = KMAppearance.Layout.l_1Color() self.outlineSearchField.backgroundColor = KMAppearance.Layout.l_1Color() self.noteSearchField.backgroundColor = KMAppearance.Layout.l_1Color() self.snapshotSearchField.wantsLayer = true self.outlineSearchField.wantsLayer = true self.noteSearchField.wantsLayer = true self.snapshotSearchField.layer?.backgroundColor = KMAppearance.Layout.l_1Color().cgColor self.outlineSearchField.layer?.backgroundColor = KMAppearance.Layout.l_1Color().cgColor self.noteSearchField.layer?.backgroundColor = KMAppearance.Layout.l_1Color().cgColor self.snapshotSearchField.layer?.borderWidth = 1.0 self.outlineSearchField.layer?.borderWidth = 1.0 self.noteSearchField.layer?.borderWidth = 1.0 self.snapshotSearchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor self.outlineSearchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor self.noteSearchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor // __block typeof(self) blockSelf = self; // _snapshotSearchField.changeCallBack = ^(NSString *changeContent) { // NSString *editContent = @""; // if (changeContent) { // editContent = changeContent; // } // [blockSelf.mainController searchFieldChangeAction:editContent]; // }; self.snapshotSearchField.isHidden = true self.snapshotSearchZoomOutButton.isHidden = true self.snapshotSearchZoomInButton.isHidden = true // _snapshotSearchField.endEditCallBack = ^(BOOL isEndEdit) { // if (isEndEdit/* && searchViewController.segmentedControl.segmentCount == 3*/) { // _snapshotSearchField.hidden = YES; // _snapshotSearchZoomOutButton.hidden = YES; // _snapshotSearchZoomInButton.hidden = YES; // _snapshotLabel.hidden = NO; // _snapshotNormalZoomOutButton.hidden = NO; // _snapshotNormalZoomInButton.hidden = NO; // } // }; self.thumbnailZoomInButton.toolTip = KMLocalizedString("Zoom In", nil) self.snapshotNormalZoomInButton.toolTip = KMLocalizedString("Zoom In", nil) self.snapshotSearchZoomInButton.toolTip = KMLocalizedString("Zoom In", nil) self.thumbnailZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil) self.snapshotNormalZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil) self.snapshotSearchZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil) self.outlineLabel.stringValue = KMLocalizedString("Outline", nil); self.outlineLabel.textColor = KMAppearance.Layout.h0Color() self.outlineAddButton.toolTip = KMLocalizedString("Add Item", nil) self.outlineAddButton.action = #selector(outlineContextMenuItemClicked_AddEntry) self.outlineAddButton.target = self self.outlineSearchButton.toolTip = KMLocalizedString("Search", nil) self.outlineMoreButton.action = #selector(leftSideViewMoreButtonAction) self.outlineMoreButton.target = self self.outlineMoreButton.tag = 302 self.outlineDoneButton.title = KMLocalizedString("Done", nil); self.outlineDoneButton.toolTip = KMLocalizedString("Done", nil); self.outlineDoneButton.setTitleColor(KMAppearance.Layout.w0Color()) self.outlineDoneButton.wantsLayer = true self.outlineDoneButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor self.outlineDoneButton.layer?.cornerRadius = 4.0 self.outlineDoneButton.action = #selector(leftSideViewDoneButtonAction) self.outlineDoneButton.target = self self.outlineDoneButton.tag = 310 self.outlineDoneButton.isHidden = true self.outlineSearchField.isHidden = true // _outlineSearchField.endEditCallBack = ^(BOOL isEndEdit) { // if (isEndEdit) { // _outlineSearchField.hidden = YES; // _outlineLabel.hidden = NO; // _outlineSearchButton.hidden = NO; // } // }; let menuOutline = NSMenu() menuOutline.addItem(title: KMLocalizedString("Ignore Case", "Menu item title"), action: #selector(toggleOutlineCaseInsensitiveSearch), target: self) (self.outlineSearchField.cell as? NSSearchFieldCell)?.searchMenuTemplate = menuOutline (self.outlineSearchField.cell as? NSSearchFieldCell)?.placeholderString = KMLocalizedString("Search Outline", nil) self.outlineSearchField.target = self let sud = UserDefaults.standard self.noteTitleLabel.stringValue = KMLocalizedString("Notes", nil); self.noteTitleLabel.textColor = KMAppearance.Layout.h0Color() self.noteMoreButton.action = #selector(leftSideViewMoreButtonAction) self.noteMoreButton.target = self self.noteMoreButton.tag = 304 self.noteMoreButton.wantsLayer = true self.moreButtonLayer = KMButtonLayer() self.noteMoreButton.layer?.addSublayer(self.moreButtonLayer!) self.moreButtonLayer?.frame = CGRectMake(0, 0, CGRectGetWidth(self.noteMoreButton.bounds), CGRectGetHeight(self.noteMoreButton.bounds)) self.moreButtonLayer?.layerType = .none self.moreButtonLayer?.isHidden = true self.noteFilterButton.action = #selector(noteFilterAction) self.noteFilterButton.target = self self.noteFilterButton.toolTip = KMLocalizedString("Sort", nil) self.noteFilterButton.wantsLayer = true self.filterButtonLayer = NSView() self.noteFilterButton.addSubview(self.filterButtonLayer!) self.filterButtonLayer?.frame = CGRectMake(14, 2, 8, 8) self.filterButtonLayer?.isHidden = true self.filterButtonLayer?.wantsLayer = true self.filterButtonLayer?.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor self.filterButtonLayer?.layer?.cornerRadius = 4.0 self.noteDoneButton.title = KMLocalizedString("Done", nil) self.noteDoneButton.toolTip = KMLocalizedString("Done", nil) self.noteDoneButton.setTitleColor(KMAppearance.Layout.w0Color()) self.noteDoneButton.wantsLayer = true self.noteDoneButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor self.noteDoneButton.layer?.cornerRadius = 4.0 self.noteDoneButton.action = #selector(leftSideViewDoneButtonAction) self.noteDoneButton.target = self self.noteDoneButton.tag = 311 self.noteDoneButton.isHidden = true self.noteSearchButton.toolTip = KMLocalizedString("Search", nil) self.noteSearchField.delegate = self self.noteSearchField.isHidden = true self.noteSearchField.endEditCallBack = { [unowned self] isEndEdit in if (isEndEdit) { self.noteSearchField.isHidden = true self.noteSearchButton.isHidden = false self.noteTitleLabel.isHidden = false } }; self.noteHeaderView.wantsLayer = true self.noteHeaderView.layer?.backgroundColor = KMAppearance.Else.textTagColor().cgColor self.noteHeaderView.layer?.cornerRadius = 1.0 let sortType = sud.integer(forKey: KMLeftSideViewNoteSortTypeKey) if (sortType == 1) { self.noteSortType = KMNoteSortType(rawValue: sortType)! if (self.noteSortType == .time) { self.sortTypeLabel.stringValue = KMLocalizedString("Time", nil) self.sortTypeBox.toolTip = KMLocalizedString("Time", nil) } else if (self._noteSortType == .page) { self.sortTypeLabel.stringValue = KMLocalizedString("Page", nil) self.sortTypeBox.toolTip = KMLocalizedString("Page", nil) } } else { self.noteSortType = .time self.sortTypeLabel.stringValue = KMLocalizedString("Time", nil) } self.sortTypeLabel.textColor = KMAppearance.Layout.h1Color() self.isAscendSort = sud.bool(forKey: KMLeftSideViewAscendSortBoolKey) if (self.isAscendSort) { self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankReverse) self.noteSortButton.toolTip = KMLocalizedString("ascending sort", nil) } else { self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankPositive) self.noteSortButton.toolTip = KMLocalizedString("descending sort", nil) } self.sortTypeBox.downCallback = { [unowned self] downEntered, mouseBox, _ in if (downEntered) { let menu = NSMenu() let timeItem = menu.addItem(title: KMLocalizedString("Time", nil), action: #selector(sortTypeAction), target: self) timeItem?.representedObject = self timeItem?.tag = 0 let pageItem = menu.addItem(title: KMLocalizedString("Page", nil), action: #selector(sortTypeAction), target: self) pageItem?.representedObject = self timeItem?.tag = 1 if (self.noteSortType == .time) { timeItem?.state = .on pageItem?.state = .off } else if (self.noteSortType == .page) { timeItem?.state = .off pageItem?.state = .on } menu.popUp(positioning: nil, at: CGPointMake(-10, 0), in: self.sortTypeBox) } } self.searchViewController.loadView() self.searchViewController.contentView = self.findTableView.enclosingScrollView self.searchField = self.searchViewController.searchField self.searchViewController.segmentedControl.setSegmentCount(2, with: 25) self.searchViewController.segmentedControl.setImage(NSImage(named: KMImageNameUXIconBtnSidebarListNor)!, for: 0) self.searchViewController.segmentedControl.setImage(NSImage(named: KMImageNameUXIconBtnSidebarPageNor)!, for: 1) self.searchViewController.segmentedControl.setToolTip(KMLocalizedString("Separate search results", nil), for: 0) self.searchViewController.segmentedControl.setToolTip(KMLocalizedString("Group search results by page", nil), for: 1) self.searchViewController.segmentedControl.isBackgroundHighlighted = true self.searchViewController.segmentedControl.selectedSegment = 0 self.searchViewController.segmentedControl.block = { [unowned self] segIndex in if segIndex == 0 { self.findPaneState = .singular self.displayFindViewAnimating(false) } else { self.findPaneState = .grouped self.displayGroupedFindViewAnimating(false) } } self.leftView.segmentedControl.block = { [unowned self] segIndex in self.toolButtonBox.isHidden = false self.toolButtonBoxLayoutConstraint.constant = 40.0 if (segIndex == 0) { if self.type.methodType == .Thumbnail { self.leftView.segmentedControl.selectedSegment = UInt8.max self.refreshMethodType(methodType: .None) return } self.refreshMethodType(methodType: .Thumbnail) DispatchQueue.main.async { self.toolButtonBox.contentView = self.thumbnailView self.displayThumbnailViewAnimating(true) } } else if (segIndex == 1) { if self.type.methodType == .Outline { self.leftView.segmentedControl.selectedSegment = UInt8.max self.refreshMethodType(methodType: .None) return } self.refreshMethodType(methodType: .Outline) DispatchQueue.main.async { self.toolButtonBox.contentView = self.outlineView self.displayTocViewAnimating(false) } } else if (segIndex == 2) { if self.type.methodType == .Annotation { self.leftView.segmentedControl.selectedSegment = UInt8.max self.refreshMethodType(methodType: .None) return } self.refreshMethodType(methodType: .Annotation) DispatchQueue.main.async { self.toolButtonBox.contentView = self.noteView self.displayNoteViewAnimating(false) } } else if (segIndex == 3) { self.toolButtonBox.contentView = self.snapshotNormalView self.displaySnapshotViewAnimating(false) self.updataLeftSideSnapView() } else if (segIndex == 4) { if self.type.methodType == .Search { self.leftView.segmentedControl.selectedSegment = UInt8.max self.refreshMethodType(methodType: .None) return } self.refreshMethodType(methodType: .Search) DispatchQueue.main.async { self.toolButtonBox.isHidden = true self.toolButtonBoxLayoutConstraint.constant = 0 self.displayFindViewAnimating(false) } } } // self.button.setHelp(KMLocalizedString("View Thumbnails", "Tool tip message"), for: KMLeftSidePaneState.thumbnail.rawValue) // self.button.setHelp(KMLocalizedString("View Outline", "Tool tip message"), for: KMLeftSidePaneState.outline.rawValue) // self.alternateButton.setHelp(KMLocalizedString("Separate search results", "Tool tip message"), for: KMFindPaneState.singular.rawValue) // self.alternateButton.setHelp(KMLocalizedString("Group search results by page", "Tool tip message"), for: KMFindPaneState.grouped.rawValue) // NSMenu *menu = [NSMenu menu]; // [menu addItemWithTitle:NSLocalizedString(@"Whole Words Only", @"Menu item title") action:@selector(toggleWholeWordSearch:) target:mainController]; // [menu addItemWithTitle:NSLocalizedString(@"Ignore Case", @"Menu item title") action:@selector(toggleCaseInsensitiveSearch:) target:mainController]; // [[searchField cell] setSearchMenuTemplate:menu]; // [[searchField cell] setPlaceholderString:NSLocalizedString(@"Search PDF", @"placeholder")]; self.searchField.action = #selector(search) self.searchField.target = self self.tocOutlineView.autoresizesOutlineColumn = false self.tocOutlineView.allowsMultipleSelection = true self.tocOutlineView.allowsEmptySelection = true self.tocOutlineView.delegate = self self.tocOutlineView.dataSource = self self.tocOutlineView.botaDelegate = self self.tocOutlineView.botaDataSource = self self.tocOutlineView.tocDelegate = self self.thumbnailTableView.delegate = self self.thumbnailTableView.dataSource = self self.thumbnailTableView.thumbDelegate = self self.thumbnailTableView.allowsMultipleSelection = true self.findTableView.delegate = self self.findTableView.dataSource = self self.findTableView.botaDelegate = self self.groupedFindTableView.delegate = self self.groupedFindTableView.dataSource = self self.groupedFindTableView.botaDelegate = self self.thumbnailTableView.menu?.delegate = self self.findTableView.menu?.delegate = self self.groupedFindTableView.menu?.delegate = self self.tocOutlineView.doubleAction = #selector(goToSelectedOutlineItem) self.tocOutlineView.target = self self.findTableView.doubleAction = #selector(goToSelectedFindResults) self.findTableView.target = self self.groupedFindTableView.doubleAction = #selector(goToSelectedFindResults) self.groupedFindTableView.target = self // [thumbnailTableView setTypeSelectHelper:[SKTypeSelectHelper typeSelectHelperWithMatchOption:SKFullStringMatch]]; // //支持拖拽的文字类型 // [thumbnailTableView registerForDraggedTypes:@[KPDFThumbnailLocalForDraggedTypes,NSFilenamesPboardType]]; // self.thumbnailTableView.registerForDraggedTypes([.localDraggedTypes, .fileURL]) self.thumbnailTableView.registerForDraggedTypes([.localDraggedTypes, .fileURL,.string,.pdf]) // self.thumbnailTableView.registerForDraggedTypes(NSFilePromiseReceiver.readableDraggedTypes.map { NSPasteboard.PasteboardType($0) }) // self.thumbnailTableView.setDraggingSourceOperationMask([.copy, .delete], forLocal: true) // [tocOutlineView setTypeSelectHelper:[SKTypeSelectHelper typeSelectHelperWithMatchOption:SKSubstringMatch]]; // [tocOutlineView registerForDraggedTypes:[NSArray arrayWithObject:kKMPDFViewOutlineDragDataType]]; // [[[findTableView tableColumnWithIdentifier:PAGE_COLUMNID] headerCell] setTitle:NSLocalizedString(@"Page", @"Table header title")]; // [[[groupedFindTableView tableColumnWithIdentifier:PAGE_COLUMNID] headerCell] setTitle:NSLocalizedString(@"Page", @"Table header title")]; // [[[groupedFindTableView tableColumnWithIdentifier:RELEVANCE_COLUMNID] dataCell] setEnabled:NO]; self.thumbnailTableView.selectionHighlightStyle = .none // NSSortDescriptor *countDescriptor = [[[NSSortDescriptor alloc] initWithKey:SKGroupedSearchResultCountKey ascending:NO] autorelease]; // [groupedFindArrayController setSortDescriptors:[NSArray arrayWithObjects:countDescriptor, nil]]; // // self.thumbnailTableView.setDraggingSourceOperationMask(.every, forLocal: false) if UserDefaults.standard.bool(forKey: SKDisableTableToolTipsKey) == false { self.tocOutlineView.hasImageToolTips = true self.findTableView.hasImageToolTips = true self.groupedFindTableView.hasImageToolTips = true } self._updateViewColor() } func displayThumbnailViewAnimating(_ animate: Bool) { self.replaceSideView(self.thumbnailTableView.enclosingScrollView!, animate: animate) var frame = self.thumbnailTableView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.origin.x = self.leftMargin frame.size.height = self.thumbnailTableView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.thumbnailTableView.enclosingScrollView?.frame = frame self.resetThumbnails() frame = self.noteOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.origin.x = self.leftMargin frame.size.height = self.noteOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.noteOutlineView.enclosingScrollView?.frame = frame frame = self.snapshotTableView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.origin.x = self.leftMargin frame.size.height = self.snapshotTableView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.snapshotTableView.enclosingScrollView?.frame = frame // [self updateThumbnailSelection]; } func displayFindViewAnimating(_ animate: Bool) { self.replaceSideView(self.searchViewController.view, animate: animate) if (self.findState != .content) { self.findState = .content } else { self.displayFindState() } var frame = self.searchViewController.view.frame frame.origin.y = 0 frame.size.height = self.searchViewController.view.superview?.frame.size.height ?? .zero self.searchViewController.view.frame = frame frame = self.noteOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.noteOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.noteOutlineView.enclosingScrollView?.frame = frame frame = self.snapshotTableView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.snapshotTableView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.snapshotTableView.enclosingScrollView?.frame = frame self.leftSideEmptyVC.emptySnapView.removeFromSuperview() self.updataLeftSideSnapView() } func displayFindState() { if (self.findState == .content) { self.displayFind() } else if (self.findState == .note) { self.displayNoteFind() } else if (self.findState == .snapshot) { self.displaySnapshotFind() } } func updataLeftSideSnapView() { if (snapshots.count < 1) { self.snapshotNormalSearchButton.isEnabled = false // leftSideController.snapshotSearchZoomOutButton.enabled = NO; self.snapshotNormalZoomOutButton.isEnabled = false // leftSideController.snapshotSearchZoomInButton.enabled = NO; self.snapshotNormalZoomInButton.isEnabled = false self.snapshotNormalMoreButton.isEnabled = false self.leftSideEmptyVC.deleteSnapBtn.isEnabled = false self.leftSideEmptyVC.exportSnapBtn.isEnabled = false self.leftSideEmptyVC.printSnapBtn.isEnabled = false self.snapshotTableView.usesAlternatingRowBackgroundColors = false let view = self.snapshotTableView.enclosingScrollView! let emptyVcSize = self.leftSideEmptyVC.emptySnapView.frame.size self.leftSideEmptyVC.emptySnapView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height); self.leftSideEmptyVC.emptySnapView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin] self.snapshotTableView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.emptySnapView) } else { self.snapshotNormalSearchButton.isEnabled = true // leftSideController.snapshotSearchZoomOutButton.enabled = YES; self.snapshotNormalZoomOutButton.isEnabled = true // leftSideController.snapshotSearchZoomInButton.enabled = YES; self.snapshotNormalZoomInButton.isEnabled = true self.snapshotNormalMoreButton.isEnabled = true self.leftSideEmptyVC.emptySnapView.removeFromSuperview() self.leftSideEmptyVC.deleteSnapBtn.isEnabled = true self.leftSideEmptyVC.exportSnapBtn.isEnabled = true self.leftSideEmptyVC.printSnapBtn.isEnabled = true } } func updataLeftSideFindView() { if (self.findState != .content) { return } if (self.searchResults.count > 0) { self.searchViewController.emptyBox.isHidden = true self.searchViewController.searchResultsView.isHidden = false self.searchViewController.searchResultsLabel.stringValue = String(format: KMLocalizedString("%ld Results", "Message in search table header"), self.searchResults.count) } else { self.searchViewController.emptyBox.isHidden = false self.searchViewController.searchResultsView.isHidden = true } } func displayGroupedFindViewAnimating(_ animate: Bool) { self.replaceSideView(self.searchViewController.view , animate: animate) if (self.findState != .content) { self.findState = .content } else { self.displayFindState() } var frame = self.searchViewController.view.frame frame.origin.y = 0 frame.size.height = self.searchViewController.view.superview?.frame.size.height ?? 0 self.searchViewController.view.frame = frame frame = self.noteOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.noteOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.noteOutlineView.enclosingScrollView?.frame = frame frame = self.snapshotTableView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.snapshotTableView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.snapshotTableView.enclosingScrollView?.frame = frame self.updataLeftSideSnapView() } func displayNoteViewAnimating(_ animate: Bool) { self.reloadAnnotation() self.searchViewController.contentView = nil self.replaceSideView(self.noteOutlineView.enclosingScrollView!, animate: animate) if (self.findState != .note) { self.findState = .note } else { self.displayFindState() } var frame = self.noteOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.noteOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.noteOutlineView.enclosingScrollView?.frame = frame frame = self.noteOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.noteOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.noteOutlineView.enclosingScrollView?.frame = frame frame = self.snapshotTableView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.snapshotTableView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.snapshotTableView.enclosingScrollView?.frame = frame let view = self.noteOutlineView.enclosingScrollView! let emptyVcSize = self.leftSideEmptyVC.emptyAnnotationView.frame.size self.leftSideEmptyVC.emptyAnnotationView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height) DispatchQueue.main.async { self.noteOutlineView.reloadData() } } func displaySnapshotViewAnimating(_ animate: Bool) { self.searchViewController.contentView = nil self.replaceSideView(self.snapshotTableView.enclosingScrollView!, animate: animate) if (self.findState != .snapshot) { self.findState = .snapshot; } else { self.displayFindState() } var frame = self.snapshotTableView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.snapshotTableView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.snapshotTableView.enclosingScrollView?.frame = frame // frame = rightSideController.noteOutlineView.enclosingScrollView.frame; // frame.origin.y = 0; // frame.size.height = rightSideController.noteOutlineView.enclosingScrollView.superview.frame.size.height; // rightSideController.noteOutlineView.enclosingScrollView.frame = frame; frame = self.tocOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.tocOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.tocOutlineView.enclosingScrollView?.frame = frame // [self updateSnapshotsIfNeeded]; } func displayFind() { self.searchField = self.searchViewController.searchField let menu = NSMenu() _ = menu.addItem(title: KMLocalizedString("Whole Words Only", "Menu item title"), action: #selector(toggleWholeWordSearch), target: self) _ = menu.addItem(title: KMLocalizedString("Ignore Case", "Menu item title"), action: #selector(toggleCaseInsensitiveSearch), target: self) (self.searchViewController.searchField.cell as? NSSearchFieldCell)?.searchMenuTemplate = menu (self.searchViewController.searchField.cell as? NSSearchFieldCell)?.placeholderString = KMLocalizedString("Search PDF", "placeholder") self.searchViewController.searchField.action = #selector(search) self.searchViewController.searchField.target = self if (self.findPaneState == .singular) { self.searchViewController.contentView = self.findTableView.enclosingScrollView self.findTableView.wantsLayer = true self.findTableView.layer?.backgroundColor = NSColor.red.cgColor DispatchQueue.main.async { self.findTableView.reloadData() } } else if (self.findPaneState == .grouped) { self.searchViewController.contentView = self.groupedFindTableView.enclosingScrollView var array = KMSearchMode.sortSearchResult(results: self.searchResults) array.sort(){$0.datas.count > $1.datas.count} self.groupSearchResults = array self.groupedFindTableView.reloadData() } } func displayTocViewAnimating(_ animate: Bool) { self.replaceSideView(self.tocOutlineView.enclosingScrollView!, animate: animate) var frame = self.tocOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.tocOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.tocOutlineView.enclosingScrollView?.frame = frame frame = self.noteOutlineView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.noteOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.noteOutlineView.enclosingScrollView?.frame = frame frame = self.snapshotTableView.enclosingScrollView?.frame ?? .zero frame.origin.y = 0 frame.size.height = self.snapshotTableView.enclosingScrollView?.superview?.frame.size.height ?? 0 self.snapshotTableView.enclosingScrollView?.frame = frame // [self updateOutlineSelection]; let view = self.tocOutlineView.enclosingScrollView! let emptyVcSize = self.leftSideEmptyVC.emptyOutlineView.frame.size self.leftSideEmptyVC.emptyOutlineView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height); } override func requiresAlternateButton(forView aview: NSView?) -> Bool { return false } func displayNoteFind() { self.searchField = self.noteSearchField let menu = NSMenu() _ = menu.addItem(title: KMLocalizedString("Ignore Case", "Menu item title"), action: #selector(toggleCaseInsensitiveNoteSearch), target: self) (self.noteSearchField.cell as? NSSearchFieldCell)?.searchMenuTemplate = menu (self.noteSearchField.cell as? NSSearchFieldCell)?.placeholderString = KMLocalizedString("Search Notes", "placeholder") self.noteSearchField.action = #selector(searchNotes) self.noteSearchField.target = self } func displaySnapshotFind() { self.searchField = self.snapshotSearchField; let menu = NSMenu() _ = menu.addItem(title: KMLocalizedString("Ignore Case", "Menu item title"), action: #selector(toggleCaseInsensitiveNoteSearch), target: self) (self.snapshotSearchField.cell as? NSSearchFieldCell)?.searchMenuTemplate = menu (self.snapshotSearchField.cell as? NSSearchFieldCell)?.placeholderString = KMLocalizedString("Search Snapshots", "placeholder") self.snapshotSearchField.action = #selector(searchNotes) self.snapshotSearchField.target = self self.snapshotSearchField.delegate = self } /* - (void)applySearchTableHeader:(NSString *)message { [[[findTableView tableColumnWithIdentifier:RESULTS_COLUMNID] headerCell] setStringValue:message]; [[findTableView headerView] setNeedsDisplay:YES]; [[[groupedFindTableView tableColumnWithIdentifier:RELEVANCE_COLUMNID] headerCell] setStringValue:message]; [[groupedFindTableView headerView] setNeedsDisplay:YES]; } */ @IBAction func search(_ sender: NSSearchField) { self.delegate?.searchAction?(searchString: sender.stringValue, isCase: false) } @IBAction func snapshotNormalSearchButtonAction(_ sender: NSButton) { self.snapshotSearchField.isHidden = false // _snapshotSearchZoomOutButton.hidden = YES; self.snapshotSearchZoomInButton.isHidden = true self.snapshotNormalSearchButton.isHidden = true self.snapshotDoneButton.isHidden = false self.snapshotLabel.isHidden = true self.snapshotNormalZoomOutButton.isHidden = true self.snapshotNormalZoomInButton.isHidden = true self.snapshotSearchField.becomeFirstResponder() } func resetThumbnails() { // [self willChangeValueForKey:THUMBNAILS_KEY]; // self.thumbnailCacheSize = 160 self.thumbnails.removeAll() let pageLabels = self.listView.document.pageLabels() if (pageLabels.isEmpty == false) { let isLocked = self.listView.document.isLocked let firstPage = self.listView.document.page(at: 0) let emptyPage = CPDFPage() let firstFrame = firstPage?.bounds(for: .cropBox) ?? .zero let firstFrame2 = firstPage?.bounds(for: .mediaBox) ?? .zero emptyPage.setBounds(firstFrame, for: .cropBox) emptyPage.setBounds(firstFrame2, for: .mediaBox) emptyPage.rotation = firstPage?.rotation ?? 0 let pageImage = firstPage!.thumbnail(of: NSMakeSize(self.thumbnailCacheSize, self.thumbnailCacheSize)) // NSImage * = [emptyPage thumbnailWithSize:thumbnailCacheSize forBox:[pdfView displayBox]]; var rect: NSRect = .zero rect.size = pageImage?.size ?? .zero let width = 1.2 * fmin(NSWidth(rect), NSHeight(rect)) rect = NSInsetRect(rect, 0.5 * (NSWidth(rect) - width), 0.5 * (NSHeight(rect) - width)); pageImage?.lockFocus() // NSImage(named: NSImage.applicationIconName)?.draw(in: rect, from: .zero, operation: .sourceOver, fraction: 0.5) if (isLocked) { NSWorkspace.shared.icon(forFileType: NSFileTypeForHFSTypeCode(OSType(kLockedBadgeIcon))).draw(in: rect, from: .zero, operation: .sourceOver, fraction: 0.5) // [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kLockedBadgeIcon)] drawInRect:rect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:0.5]; } pageImage?.unlockFocus() for (i, label) in pageLabels.enumerated() { let firstPage = self.listView.document.page(at: UInt(i)) let size = NSMakeSize(self.thumbnailCacheSize, self.thumbnailCacheSize) // let pageImage = firstPage!.thumbnail(of: size) let thumbnail = KMThumbnail(image: nil, label: label, pageIndex: i) // thumbnail.delegate = self thumbnail.dirty = true self.thumbnails.append(thumbnail) } } // [self didChangeValueForKey:THUMBNAILS_KEY]; // [self allThumbnailsNeedUpdate]; DispatchQueue.main.async { self.thumbnailTableView.reloadData() } } @IBAction @objc func sortTypeAction(_ sender: NSMenuItem) { let item = sender let tag = item.tag if (item.state == .on) { item.state = .off } else { item.state = .on } if (tag == 0) { self.noteSortType = .page self.sortTypeLabel.stringValue = KMLocalizedString("Page", nil) self.sortTypeBox.toolTip = KMLocalizedString("Page", nil) } else if (tag == 1) { self.noteSortType = .time self.sortTypeLabel.stringValue = KMLocalizedString("Time", nil) self.sortTypeBox.toolTip = KMLocalizedString("Time", nil) } UserDefaults.standard.set(self.noteSortType.rawValue, forKey: KMLeftSideViewNoteSortTypeKey) UserDefaults.standard.synchronize() } @IBAction func noteSortAction(_ sender: AnyObject?) { if (self.isAscendSort) { self.isAscendSort = false self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankPositive) self.noteSortButton.toolTip = KMLocalizedString("descending sort", nil) } else { self.isAscendSort = true self.noteSortButton.image = NSImage(named: KMImageNameBtnSidebarRankReverse) self.noteSortButton.toolTip = KMLocalizedString("ascending sort", nil) } UserDefaults.standard.setValue(self.isAscendSort, forKey: KMLeftSideViewAscendSortBoolKey) UserDefaults.standard.synchronize() } @IBAction func noteSearchAction(_ sender: NSButton) { self.noteSearchField.isHidden = false self.noteTitleLabel.isHidden = true self.noteSearchButton.isHidden = true self.noteDoneButton.isHidden = false self.noteFilterButton.isHidden = true self.noteMoreButton.isHidden = true self.noteSearchField.becomeFirstResponder() } @IBAction func leftSideViewDoneButtonAction(_ sender: AnyObject?) { let button = sender as? NSButton let tag = button?.tag ?? 0 if (tag == 310) { self.outlineSearchField.isHidden = true self.outlineDoneButton.isHidden = true self.outlineLabel.isHidden = false self.outlineSearchButton.isHidden = false self.outlineMoreButton.isHidden = false self.outlineAddButton.isHidden = false } else if (tag == 311) { self.noteSearchField.isHidden = true self.noteTitleLabel.isHidden = false self.noteSearchButton.isHidden = false self.noteDoneButton.isHidden = true self.noteFilterButton.isHidden = false self.noteMoreButton.isHidden = false } else if (tag == 312) { self.snapshotSearchField.isHidden = true // leftSideController.snapshotSearchZoomOutButton.hidden = YES; // leftSideController.snapshotSearchZoomInButton.hidden = YES; self.snapshotNormalSearchButton.isHidden = false self.snapshotDoneButton.isHidden = true self.snapshotLabel.isHidden = false self.snapshotNormalZoomOutButton.isHidden = false self.snapshotNormalZoomInButton.isHidden = false } } @IBAction func leftSideViewMoreButtonAction(_ sender: AnyObject?) { let button = sender as? NSButton let tag = button?.tag ?? 0 if (tag == 300) { // NSInteger selectedRow = 0; // if (rightSideController.snapshotTableView.selectedRow >= 0) { // selectedRow = rightSideController.snapshotTableView.selectedRow; // } else { // return; // } // SKSnapshotWindowController *controller = [[rightSideController.snapshotArrayController arrangedObjects] objectAtIndex:selectedRow]; // NSMenu *menu = [[[NSMenu alloc] init] autorelease]; // NSMenuItem *itemExport = [menu addItemWithTitle:NSLocalizedString(@"Export", @"Menu item title") action:nil target:self]; // NSMenu *subMenu = [NSMenu menu]; // // NSMenuItem *t = [subMenu addItemWithTitle:NSLocalizedString(@"PNG", @"Menu item title") action:@selector(menuItemClick_ExportPNG:) target:self]; // [t setRepresentedObject:controller]; // // t = [subMenu addItemWithTitle:NSLocalizedString(@"JPG", @"Menu item title") action:@selector(menuItemClick_ExportJPG:) target:self]; // [t setRepresentedObject:controller]; // // t = [subMenu addItemWithTitle:NSLocalizedString(@"PDF", @"Menu item title") action:@selector(menuItemClick_ExportPDF:) target:self]; // [t setRepresentedObject:controller]; // itemExport.submenu = subMenu; // // NSMenuItem *itemPrint = [menu addItemWithTitle:NSLocalizedString(@"Print", @"Menu item title") action:@selector(menuItemClick_Print:) target:self]; // [itemPrint setRepresentedObject:controller]; // [menu addItem:[NSMenuItem separatorItem]]; // // NSMenuItem *itemSelectAll = [menu addItemWithTitle:NSLocalizedString(@"Select All", @"Menu item title") action:@selector(menuItemClick_SelectAll:) target:self]; // [itemSelectAll setRepresentedObject:controller]; // [menu addItem:[NSMenuItem separatorItem]]; // // NSMenuItem *itemDeleteAllSnapshot = [menu addItemWithTitle:NSLocalizedString(@"Delete All Snapshots", @"Menu item title") action:@selector(deleteAllSnapshot:) target:self]; // [itemDeleteAllSnapshot setRepresentedObject:controller]; // // [NSMenu popUpContextMenu:menu withEvent:[NSApp currentEvent] forView:(NSButton *)sender]; } else if (tag == 302) { let menu = NSMenu() // NSMenuItem *addEntryItem = [menu addItemWithTitle:NSLocalizedString(@"Add Item", nil) action:@selector(outlineContextMenuItemClicked_AddEntry:) target:self]; // [addEntryItem setRepresentedObject:self.leftSideController.tocOutlineView]; // NSMenuItem *addChildItem = [menu addItemWithTitle:NSLocalizedString(@"Add Sub-Item", nil) action:@selector(outlineContextMenuItemClicked_AddChildEntry:) target:self]; // [addChildItem setRepresentedObject:self.leftSideController.tocOutlineView]; // [menu addItem:[NSMenuItem separatorItem]]; // // NSMenuItem *setDestinationItem = [menu addItemWithTitle:NSLocalizedString(@"Change Destination", nil) action:@selector(outlineContextMenuItemClicked_SetDestination:) target:self]; // [setDestinationItem setRepresentedObject:self.leftSideController.tocOutlineView]; // [menu addItem:[NSMenuItem separatorItem]]; let expandAllCommentsItem = menu.addItem(title: KMLocalizedString("Expand All", nil), action: #selector(toc_expandAllComments), target: self) expandAllCommentsItem?.representedObject = self.tocOutlineView let foldAllCommentsItem = menu.addItem(title: KMLocalizedString("Collapse All", nil), action: #selector(toc_foldAllComments), target: self) expandAllCommentsItem?.representedObject = self.tocOutlineView let item = self.listView.document.outlineRoot() var num = 0 for i in 0 ..< Int(item?.numberOfChildren ?? 0) { let outline = item?.child(at: UInt(i)) if self.tocOutlineView.isItemExpanded(outline) { num += 1 } } if let cnt = item?.numberOfChildren, cnt > 0 && num == 0 { self.tocType = .fold } else if let cnt = item?.numberOfChildren, cnt > 0 && num == cnt { self.tocType = .unfold } else { self.tocType = .none } if (self.tocType == .unfold) { expandAllCommentsItem?.state = .on foldAllCommentsItem?.state = .off } else if (self.tocType == .fold) { expandAllCommentsItem?.state = .off foldAllCommentsItem?.state = .on } else { expandAllCommentsItem?.state = .off foldAllCommentsItem?.state = .off } let removeEntryItem = menu.addItem(title: KMLocalizedString("Remove All Outlines", nil), action: #selector(leftSideEmptyAnnotationClick_DeleteOutline), target: self) removeEntryItem?.representedObject = self.tocOutlineView NSMenu.popUpContextMenu(menu, with: NSApp.currentEvent!, for: sender as! NSButton) } else if (tag == 304) { let menu = NSMenu() let object = KMPopupMenuObject() object.menuTag = 1001 menu.delegate = object object.enterControllerCallback = { [weak self] isEnter in if (isEnter) { self?.moreButtonLayer?.isHidden = false } else { self?.moreButtonLayer?.isHidden = true } } let expandAllCommentsItem = menu.addItem(title: KMLocalizedString("Expand All", nil), action: #selector(note_expandAllComments), target: self) expandAllCommentsItem?.representedObject = self.noteOutlineView let foldAllCommentsItem = menu.addItem(title: KMLocalizedString("Collapse All", nil), action: #selector(note_foldAllComments), target: self) foldAllCommentsItem?.representedObject = self.noteOutlineView if (self.foldType == .unfold) { expandAllCommentsItem?.state = .on foldAllCommentsItem?.state = .off } else if (self.foldType == .fold) { expandAllCommentsItem?.state = .off foldAllCommentsItem?.state = .on } else { expandAllCommentsItem?.state = .off foldAllCommentsItem?.state = .off } let showAnnotationItem = menu.addItem(title: KMLocalizedString("Show Note", nil), action: nil, target: self) let subMenu = NSMenu() // NSMenuItem *t = [subMenu addItemWithTitle:NSLocalizedString(@"Type", nil) action:@selector(noteShowNoteAction:) target:self]; // if ([[self.noteTypeDict objectForKey:@"kKMNoteFilterAnnotationTypeKey"] boolValue]) { // [t setState:NSControlStateValueOff]; // } else { // [t setState:NSControlStateValueOn]; // } // [t setRepresentedObject:self.rightSideController.noteOutlineView]; // t.tag = 100; var t = subMenu.addItem(title: KMLocalizedString("Page", nil), action: #selector(noteShowNoteAction), target: self) let pageKey = self.noteTypeDict["kKMNoteFilterAnnotationPageKey"] as? Bool ?? false if pageKey { t?.state = .off } else { t?.state = .on } t?.representedObject = self.noteOutlineView t?.tag = 101 t = subMenu.addItem(title: KMLocalizedString("Time", nil) , action: #selector(noteShowNoteAction), target: self) let timeKey = self.noteTypeDict["kKMNoteFilterAnnotationTimeKey"] as? Bool ?? false if timeKey { t?.state = .off } else { t?.state = .on } t?.representedObject = self.noteOutlineView t?.tag = 102 t = subMenu.addItem(title: KMLocalizedString("Author", nil) , action: #selector(noteShowNoteAction), target: self) let authorKey = self.noteTypeDict["kKMNoteFilterAnnotationAutherKey"] as? Bool ?? false if authorKey { t?.state = .off } else { t?.state = .on } t?.representedObject = self.noteOutlineView t?.tag = 103 showAnnotationItem?.submenu = subMenu menu.addItem(.separator()) let exportAnnotationsItem = menu.addItem(title: NSLocalizedString("Export Annotations…", tableName: "MainMenu", comment: ""), action: nil, target: self) let subMenu2 = NSMenu() var t2 = subMenu2.addItem(title: NSLocalizedString("PDF", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) t2?.representedObject = self.noteOutlineView t2?.tag = 0 t2 = subMenu2.addItem(title: NSLocalizedString("PDF Bundle", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) t2?.representedObject = self.noteOutlineView t2?.tag = 1 t2 = subMenu2.addItem(title: NSLocalizedString("PDF Reader Pro Edition Notes", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) t2?.representedObject = self.noteOutlineView t2?.tag = 2 t2 = subMenu2.addItem(title: NSLocalizedString("Notes as Text", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) t2?.representedObject = self.noteOutlineView t2?.tag = 3 t2 = subMenu2.addItem(title: NSLocalizedString("Notes as RTF", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) t2?.representedObject = self.noteOutlineView t2?.tag = 4 t2 = subMenu2.addItem(title: NSLocalizedString("Notes as RTFD", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) t2?.representedObject = self.noteOutlineView t2?.tag = 5 t2 = subMenu2.addItem(title: NSLocalizedString("Notes as FDF", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) t2?.representedObject = self.noteOutlineView t2?.tag = 6 exportAnnotationsItem?.submenu = subMenu2 menu.addItem(.separator()) let removeAllAnnotationsItem = menu.addItem(title: NSLocalizedString("Remove All Annotations", tableName: "MainMenu", comment: ""), action: #selector(leftSideEmptyAnnotationClick_DeleteAnnotation), target: self) removeAllAnnotationsItem?.representedObject = self.noteOutlineView NSMenu.popUpContextMenu(menu, with: NSApp.currentEvent!, for: button!, with: nil) } } @IBAction func note_expandAllComments(_ sender: AnyObject?) { if (self.foldType == .unfold) { return } self.foldType = .unfold // [self loadUnfoldDate:KMFoldAllAnnotationType_None]; self.noteOutlineView.reloadData() } @IBAction func note_foldAllComments(_ sender: AnyObject?) { if (self.foldType == .fold) { return } self.foldType = .fold // [self loadUnfoldDate:KMFoldAllAnnotationType_None]; self.noteOutlineView.reloadData() } @IBAction func noteShowNoteAction(_ sender: AnyObject?) { let item = sender as? NSMenuItem let tag = item?.tag ?? 0 if (tag == 100) { // BOOL isType = [[self.noteTypeDict objectForKey:@"kKMNoteFilterAnnotationTypeKey"] boolValue]; // [self.noteTypeDict setObject:[NSNumber numberWithBool:!isType] forKey:@"kKMNoteFilterAnnotationTypeKey"]; } else if (tag == 101) { let isPage = self.noteTypeDict["kKMNoteFilterAnnotationPageKey"] as? Bool ?? false self.noteTypeDict["kKMNoteFilterAnnotationPageKey"] = isPage } else if (tag == 102) { let isTime = self.noteTypeDict["kKMNoteFilterAnnotationTimeKey"] as? Bool ?? false self.noteTypeDict["kKMNoteFilterAnnotationTimeKey"] = isTime } else if (tag == 103) { let isAuther = self.noteTypeDict["kKMNoteFilterAnnotationAutherKey"] as? Bool ?? false self.noteTypeDict["kKMNoteFilterAnnotationAutherKey"] = isAuther } UserDefaults.standard.set(self.noteTypeDict, forKey: "KMNoteOutlineViewTableColumnKey") UserDefaults.standard.synchronize() let selectRow = self.noteOutlineView.selectedRow self.noteOutlineView.reloadData() self.noteOutlineView.selectRowIndexes(IndexSet(integer: selectRow), byExtendingSelection: false) } @objc func exportAnnotationNotes(_ sender: AnyObject?) { self.mainViewController.myDocument?.saveTo(sender) } @objc func leftSideEmptyAnnotationClick_DeleteAnnotation(_ sender: AnyObject?) { // NSAlert* alert = [[NSAlert alloc] init]; // [alert setAlertStyle:NSAlertStyleCritical]; // [alert setMessageText:NSLocalizedString(@"This will permanently remove all annotations. Are you sure to continue?", nil)]; // [alert addButtonWithTitle:NSLocalizedString(@"Yes", nil)]; // [alert addButtonWithTitle:NSLocalizedString(@"No", nil)]; // // NSModalResponse response = [alert runModal]; // if (response == NSAlertFirstButtonReturn) { // NSMutableArray *annotations = [NSMutableArray array]; // // for (NSUInteger i = 0; i < self.pdfView.document.pageCount; i++) { // PDFPage *page = [[self.pdfView document] pageAtIndex:i]; // for (PDFAnnotation *annotation in [page annotations]) { // if ([annotation isKindOfClass:[PDFAnnotationTextWidget class]] || // [annotation isKindOfClass:[PDFAnnotationButtonWidget class]] || // [annotation isKindOfClass:[PDFAnnotationChoiceWidget class]]) { // continue; // } // if (@available(macOS 10.13, *)) { // if ([annotation.widgetFieldType isEqualToString:PDFAnnotationWidgetSubtypeSignature]) { // continue; // } // } // if ([annotation isKindOfClass:[PDFAnnotationLink class]]) { // continue; // } // [annotations addObject:annotation]; // } // } // // for (PDFAnnotation *annotation in annotations) { // [self.pdfView removeAnnotation:annotation]; // } // } } @IBAction func noteFilterAction(_ sender: AnyObject?) { let button = sender as? NSButton let menu = NSMenu() let filterViewController = KMNoteOutlineFilterViewController() filterViewController.view.layer?.backgroundColor = .clear var notes = NSMutableArray() for section in self._annotations { if section.annotations?.count != 0 { for item in section.annotations! { notes.add(item.annotation!) } } } filterViewController.setNotesArray(notes) filterViewController.applyFilterCallback = { [weak self] typeArr, colorArr, authorArr, isEmpty in menu.cancelTracking() if (isEmpty) { self?.filterButtonLayer?.isHidden = true } else { self?.filterButtonLayer?.isHidden = false } // // [blockSelf annotationSort:@[typeArr, colorArr, authorArr]]; } filterViewController.cancelCallback = { isCancel in if (isCancel) { menu.cancelTracking() } } let item = menu.addItem(withTitle: "", action: nil, keyEquivalent: "") item.target = self item.representedObject = filterViewController item.view = filterViewController.view menu.popUp(positioning: nil, at: CGPointMake(-130, 30), in: button) } @IBAction func outlineNormalSearchButtonAction(_ sender: NSButton) { self.outlineSearchField.isHidden = false self.outlineDoneButton.isHidden = false self.outlineLabel.isHidden = true self.outlineSearchButton.isHidden = true self.outlineMoreButton.isHidden = true self.outlineAddButton.isHidden = true self.outlineSearchField.becomeFirstResponder() } // @objc func outlineContextMenuItemClicked_AddEntry(_ sender: NSMenuItem) { // NSMutableArray *PDFOutlineArray = [[NSMutableArray new] autorelease]; // NSIndexSet *rowSet = [self selectedRowIndexes] ; // // [rowSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { // [PDFOutlineArray addObject:[leftSideController.tocOutlineView itemAtRow:idx]]; // }]; // // if (PDFOutlineArray.count == 0) { // PDFOutline *lastPDFLine = [leftSideController.tocOutlineView itemAtRow:leftSideController.tocOutlineView.numberOfRows - 1]; // // PDFOutline *rootPDFOutline; // if (lastPDFLine) { // while (lastPDFLine.parent) { // lastPDFLine = lastPDFLine.parent; // } // rootPDFOutline = lastPDFLine; // } else { // rootPDFOutline = self.pdfView.document.outlineRoot; // if (!rootPDFOutline) { // rootPDFOutline = [[[PDFOutline alloc] init] autorelease]; // [self.pdfView.document setOutlineRoot:rootPDFOutline]; // } // } // // PDFOutline *addOutLine = [[[PDFOutline alloc] init] autorelease]; // addOutLine.label = [NSString stringWithFormat:@"%@ %ld",NSLocalizedString(@"Page", nil) ,[self.pdfView.document indexForPage:self.pdfView.currentDestination.page] + 1]; // addOutLine.destination = self.pdfView.currentDestination; // [self addoutlineWithParent:rootPDFOutline addOutline:addOutLine index:rootPDFOutline.numberOfChildren needExpand:NO]; // // } else { // PDFOutline *currentPDFline = PDFOutlineArray.lastObject; // NSInteger currentIndex = currentPDFline.index; // PDFOutline *parent; // parent = currentPDFline.parent; // // PDFOutline *addOutLine = [[[PDFOutline alloc] init] autorelease]; // addOutLine.label = [NSString stringWithFormat:@"%@ %ld",NSLocalizedString(@"Page", nil) ,[self.pdfView.document indexForPage:self.pdfView.currentDestination.page] + 1]; // addOutLine.destination = self.pdfView.currentDestination; // [self addoutlineWithParent:parent addOutline:addOutLine index:currentIndex + 1 needExpand:NO]; // [self.leftSideController.tocOutlineView scrollRowToVisible:currentIndex + 1]; // [self.leftSideController.tocOutlineView deselectRow:currentIndex+1]; // // } // } @IBAction func toc_expandAllComments(_ sender: AnyObject?) { if (self.tocType == .unfold) { return } self.tocType = .unfold self.tocOutlineView.reloadData() self.tocOutlineView.expandItem(nil, expandChildren: true) } @IBAction func toc_foldAllComments(_ sender: AnyObject?) { if (self.tocType == .fold) { return } self.tocType = .fold self.tocOutlineView.reloadData() self.tocOutlineView.collapseItem(nil, collapseChildren: true) } @objc func leftSideEmptyAnnotationClick_DeleteOutline(_ sender: AnyObject?) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = "" alert.informativeText = KMLocalizedString("This will permanently remove all outlines. Are you sure to continue?", nil) alert.addButton(withTitle: KMLocalizedString("Yes", nil)) alert.addButton(withTitle: KMLocalizedString("No", nil)) let response = alert.runModal() if response == .alertFirstButtonReturn { if let item = self.listView.document.outlineRoot() { self.removeAllOutline(item) } } } @IBAction func thumbnailSizeScaling(_ sender: NSButton) { let sud = UserDefaults.standard let tag = sender.tag if (tag == 0 || tag == 1) { var scaling = sud.float(forKey: "KMThumbnailSizeScalingKey") if (scaling <= 0) { scaling = 1 } if (tag == 0) { // thumbnail Zoom In scaling += 0.1 if scaling >= 2.2 { return } } else if (tag == 1) { // thumbnail Zoom Out scaling -= 0.1 if scaling <= 0.4 { return } } sud.setValue(scaling, forKey: "KMThumbnailSizeScalingKey") let selectRow = self.thumbnailTableView.selectedRow self.thumbnailTableView.reloadData() self.thumbnailTableView.selectRowIndexes(IndexSet(integer: selectRow), byExtendingSelection: false) } else if (tag == 2 || tag == 3) { var scaling = sud.float(forKey: "KMSnapshotSizeScalingKey") if (scaling <= 0) { scaling = 1 } if (tag == 2) { // snapshot Zoom In scaling += 0.1 } else if (tag == 3) { // snapshot Zoom Out scaling -= 0.1 } sud.setValue(scaling, forKey: "KMSnapshotSizeScalingKey") let selectRow = self.snapshotTableView.selectedRow self.snapshotTableView.reloadData() self.snapshotTableView.selectRowIndexes(IndexSet(integer: selectRow), byExtendingSelection: false) } } func reloadAnnotation() { if self.listView != nil { var dataArray: [KMBOTAAnnotationSection] = [] var annotationArray: [CPDFAnnotation] = [] for i in 0 ..< self.listView.document.pageCount { var annotationItemArray: [KMBOTAAnnotationItem] = [] let page = self.listView.document.page(at: i) let types = ["Highlight","Underline","Strikeout","Freehand","FreeText","Note","Square","Circle","Line","Stamp","Arrow","Image","Redact","Sign"] var pageAnnotations: [CPDFAnnotation] = KMOCToolClass.filterAnnotation(annotations: page!.annotations,types: types) as! [CPDFAnnotation] //添加签名注释 for annotation in page!.annotations { if annotation.isKind(of: CPDFSignatureAnnotation.self) { pageAnnotations.append(annotation) } } for annotation in pageAnnotations { if annotation.annotationShouldDisplay() == false { pageAnnotations.removeObject(annotation) } } //转换所有annotation类型 let section = KMBOTAAnnotationSection() for annotation in pageAnnotations { let item = KMBOTAAnnotationItem() item.section = section item.annotation = annotation item.index = Int(annotation.page.pageIndex()) annotationItemArray.append(item) } if annotationItemArray.count != 0 { section.annotations = annotationItemArray section.page = page section.isItemExpanded = true dataArray.append(section) } //添加所有annotation 用于筛选 annotationArray += pageAnnotations } //转换对象,用于数据显示 self._annotations = dataArray self._allAnnotations = annotationArray // if self.annotations.count < 1 { // self.filtrateButton.isEnabled = false // } else { // self.filtrateButton.isEnabled = true // } } } func annotationSort(sortArray:[[Any]]) { if self.listView != nil { var typeArr: [Any] = [] var colorArr: [Any] = [] var authorArr: [Any] = [] let sud = UserDefaults.standard let typeData = sud.object(forKey: "KMNoteOutlineFilterSelectArray_Type" + self.listView.document.documentURL.path) as? Data if typeData != nil { typeArr = NSKeyedUnarchiver.unarchiveObject(with: typeData!) as! [Any] } let colorData = sud.object(forKey: "KMNoteOutlineFilterSelectArray_Color" + self.listView.document.documentURL.path) as? Data if colorData != nil { colorArr = NSKeyedUnarchiver.unarchiveObject(with: colorData!) as! [Any] } let authorData = sud.object(forKey: "KMNoteOutlineFilterSelectArray_Author" + self.listView.document.documentURL.path) as? Data if authorData != nil { authorArr = NSKeyedUnarchiver.unarchiveObject(with: authorData!) as! [Any] } if typeArr.count == 0 && colorArr.count == 0 && authorArr.count == 0 { // self.filtrateButton.image = NSImage(named: "KMImageNameAnnotationsFiltrate") self.reloadAnnotation() } else { // self.filtrateButton.image = NSImage(named: "icon_annotation_screening_select") var dataArray: [KMBOTAAnnotationSection] = [] for i in 0 ..< self.listView.document.pageCount { var annotationItemArray: [KMBOTAAnnotationItem] = [] let page = self.listView.document.page(at: i) if page!.annotations.count > 0 { var filterAnnotations: [CPDFAnnotation] = page!.annotations if typeArr.count > 0 { filterAnnotations = (KMOCToolClass.filterAnnotation(annotations: filterAnnotations, types: typeArr) as! [CPDFAnnotation]) } if (colorArr.count > 0) { filterAnnotations = (KMOCToolClass.filterAnnotation(annotations: filterAnnotations,colors: colorArr) as! [CPDFAnnotation]) } if (authorArr.count > 0) { filterAnnotations = (KMOCToolClass.filterAnnotation(annotations: filterAnnotations,authors: authorArr) as! [CPDFAnnotation]) } let section = KMBOTAAnnotationSection() for annotation in filterAnnotations { let item = KMBOTAAnnotationItem() item.section = section item.annotation = annotation item.index = Int(page!.pageIndex()) annotationItemArray.append(item) } if annotationItemArray.count != 0 { section.annotations = annotationItemArray section.page = page section.isItemExpanded = true dataArray.append(section) } } } self._annotations = dataArray } } } func showSearchOutlineBlankState(_ toShowState: Bool) { if (toShowState) { self.leftSideEmptyVC.outlineSearchView.frame = CGRectMake((self.tocOutlineView.enclosingScrollView!.documentView!.frame.size.width - self.leftSideEmptyVC.outlineSearchView.bounds.size.width)/2.0, (self.tocOutlineView.enclosingScrollView!.documentView!.frame.size.height - self.leftSideEmptyVC.outlineSearchView.bounds.size.height)/2.0, self.leftSideEmptyVC.outlineSearchView.bounds.size.width, self.leftSideEmptyVC.outlineSearchView.bounds.size.height); self.tocOutlineView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.outlineSearchView) self.leftSideEmptyVC.outlineSearchView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin] } else { self.leftSideEmptyVC.outlineSearchView.removeFromSuperview() } } // func allRangeOfRoughString(_ roughString: String, searchString: String) -> [NSRange] { // // } func removeAllOutline(_ outline: CPDFOutline) { let ol = CPDFOutline() self.listView.document.setOutlineRoot(ol) for i in 0 ..< self.listView.document.pageCount { self.listView.document.removeBookmark(forPageIndex: i) } self.listView.layoutDocumentView() DispatchQueue.main.async { self.tocOutlineView.reloadData() } } func updateNoteFilterPredicate() { //注释筛选 // [rightSideController.noteArrayController setFilterPredicate:[noteTypeSheetController filterPredicateForSearchString:[rightSideController.searchField stringValue] caseInsensitive:mwcFlags.caseInsensitiveNoteSearch]]; // NSPredicate *predicate = [noteTypeSheetController filterPredicateForSearchString:[rightSideController.searchField stringValue] caseInsensitive:mwcFlags.caseInsensitiveNoteSearch]; // [self loadAnnotationSortData:[NSArray arrayWithObjects:predicate, nil]]; // [rightSideController.noteOutlineView reloadData]; } @objc func selectSelectedNote(_ sender: AnyObject?) { if self.listView.hideNotes == false { let selectedNotes = self.selectedNotes() if selectedNotes.count == 1 { let annotation = selectedNotes.last! self.listView.go(to: annotation.bounds, on: annotation.page, animated: true) // [pdfView scrollAnnotationToVisible:annotation]; // [pdfView setActiveAnnotation:annotation]; self.listView.updateActiveAnnotations([annotation]) self.listView.setNeedsDisplayAnnotationViewForVisiblePages() // } } // NSInteger column = [sender clickedColumn]; // if (column != -1) { // NSString *colID = [[[sender tableColumns] objectAtIndex:column] identifier]; // // if ([colID isEqualToString:@"color"]){ // for (PDFAnnotation *annotation in self.pdfView.activeAnnotations) { // if (![annotation isKindOfClass:[PDFAnnotationChoiceWidget class]] && // ![annotation isKindOfClass:[PDFAnnotationButtonWidget class]] && // ![annotation isKindOfClass:[PDFAnnotationTextWidget class]]) { // [[NSColorPanel sharedColorPanel] orderFront:nil]; // break; // } // // } // } // } } } func selectedNotes() -> [CPDFAnnotation] { var selectedNotes: [CPDFAnnotation] = [] let rowIndexes = self.noteOutlineView.selectedRowIndexes for row in rowIndexes { let item = self.noteOutlineView.item(atRow: row) if item is KMBOTAAnnotationItem { if let anno = (item as! KMBOTAAnnotationItem).annotation { // if anno.type == nil { // item = [(SKNoteText *)item note]; // } if selectedNotes.contains(anno) == false { selectedNotes.append(anno) } } } } return selectedNotes } } // MARK: - KMBotaTableViewDelegate extension KMLeftSideViewController: KMBotaTableViewDelegate { func tableView(_ aTableView: NSTableView, canCopyRowsWithIndexes rowIndexes: IndexSet) -> Bool { if aTableView.isEqual(to: self.thumbnailTableView) || aTableView.isEqual(to: self.findTableView) || aTableView.isEqual(to: self.groupedFindTableView) { return rowIndexes.count > 0 } return false } func tableView(_ aTableView: NSTableView, canPasteFromPasteboard pboard: NSPasteboard) -> Bool { if aTableView.isEqual(to: self.thumbnailTableView) { if self._copysPages.count > 0 { return true } } return false } func tableView(_ aTableView: NSTableView, canDeleteRowsWithIndexes rowIndexes: IndexSet) -> Bool { // if ([tv isEqual:rightSideController.snapshotTableView]) { // return [rowIndexes count] > 0; // } else if aTableView.isEqual(to: self.thumbnailTableView) { if self.listView.document.pageCount <= 1 { return false } return true } return false } func tableView(_ aTableView: NSTableView, pasteFromPasteboard pboard: NSPasteboard) { // if (![IAPProductsManager defaultManager].isAvailableAllFunction) { // [[KMPurchaseCompareWindowController sharedInstance] showWindow:nil]; // return; // } if aTableView.isEqual(to: self.thumbnailTableView) { if self._copysPages.count > 0 { let index = self.listView.document.index(for: self.listView.currentPage()) + 1 if (index == NSNotFound) { return } for page in self._copysPages.reversed() { if let newPage = page.copy() as? CPDFPage { self.listView.document.insertPageObject(newPage, at: index) } self.listView.layoutDocumentView() // [pageLabels setArray:[[pdfView document] pageLabels]]; self.resetThumbnails() let pageIndex = min(index, self.listView.document.pageCount-1) self.listView.go(toPageIndex: Int(pageIndex), animated: true) // [[[[self document] undoManager] prepareWithInvocationTarget:self] tableView:leftSideController.thumbnailTableView deleteRowsWithIndexes:[NSIndexSet indexSetWithIndex:index]]; } } } } func tableViewMoveLeft(_ aTableView: NSTableView) { if aTableView.isEqual(to: self.findTableView) || aTableView.isEqual(to: self.groupedFindTableView) { // [self updateFindResultHighlightsForDirection:NSSelectingPrevious]; } } func tableViewMoveRight(_ aTableView: NSTableView) { if aTableView.isEqual(to: self.findTableView) || aTableView.isEqual(to: self.groupedFindTableView) { // [self updateFindResultHighlightsForDirection:NSSelectingNext]; } } func tableView(_ aTableView: NSTableView, imageContextForRow rowIndex: Int) -> AnyObject? { if aTableView.isEqual(to: self.findTableView) { if rowIndex >= self.searchResults.count { return nil } let model = self.searchResults[rowIndex] let selection = model.selection let point = NSPoint(x: NSWidth(selection.bounds) * 0.5, y: NSHeight(selection.bounds) * 0.5) return CPDFDestination(document: self.listView.document, pageIndex: Int(selection.page.pageIndex()), at: point, zoom: self.listView.scaleFactor) } else if aTableView.isEqual(to: self.groupedFindTableView) { if rowIndex >= self.groupSearchResults.count { return nil } // let model = self.groupSearchResults[rowIndex] // let selection = model.selection // let point = NSPoint(x: NSWidth(selection.bounds) * 0.5, y: NSHeight(selection.bounds) * 0.5) // return CPDFDestination(document: self.listView.document, pageIndex: Int(selection.page.pageIndex()), at: point, zoom: self.listView.scaleFactor) } return nil } /* - (NSArray *)tableView:(NSTableView *)tv typeSelectHelperSelectionStrings:(SKTypeSelectHelper *)typeSelectHelper { if ([tv isEqual:leftSideController.thumbnailTableView]) { return pageLabels; } return nil; } - (void)tableView:(NSTableView *)tv typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper didFailToFindMatchForSearchString:(NSString *)searchString { if ([tv isEqual:leftSideController.thumbnailTableView]) { [statusBar setLeftStringValue:[NSString stringWithFormat:NSLocalizedString(@"No match: \"%@\"", @"Status message"), searchString]]; } } - (void)tableView:(NSTableView *)tv typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper updateSearchString:(NSString *)searchString { if ([tv isEqual:leftSideController.thumbnailTableView]) { if (searchString.length > 0) [statusBar setLeftStringValue:[NSString stringWithFormat:NSLocalizedString(@"Go to page: %@", @"Status message"), searchString]]; else [self updateLeftStatus]; } } */ } // 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: - 扩展 extension KMLeftSideViewController { public func selectType(_ type: BotaType) { // 更新 type var show = true if (self.type.methodType == .None) { show = true } else { if (self.type.methodType == type) { show = false } else { show = true } } var index: Int = NSNotFound switch type { case .None: index = NSNotFound break case .Thumbnail: index = 0 break case .Outline: index = 1 break case .BookMark: index = 2 break case .Annotation: index = 3 break case .Search: index = 4 break case .From: index = 5 break case .Signature: index = 6 break } self.type = self.getMethodMode(show ? type : .None) // 更新按钮状态 // self.updateViewButtonState() // 将事件传递出去 self.delegate?.controlStateChange?(self,show:show) if (index != NSNotFound) { // 记录当前选中 UserDefaults.standard.set(index, forKey: "KMBOTASelectedIndexKey") UserDefaults.standard.synchronize() } } private func getMethodMode(_ type: BotaType) -> KMLeftMethodMode { let mode = KMLeftMethodMode() mode.methodType = type switch type { case .None: mode.methodName = "" break case .Thumbnail: mode.methodName = thumbnailMethodKey break case .Outline: mode.methodName = outlineMethodKey break case .BookMark: mode.methodName = bookMarkMethodKey break case .Annotation: mode.methodName = anntationMethodKey break case .Search: mode.methodName = searchMethodKey break case .From: mode.methodName = formMethodKey break case .Signature: mode.methodName = signatureMethodKey break } return mode } } //MARK: Cache extension KMLeftSideViewController { func clearAnnotationFilterData() { if let _key = self.listView?.document?.documentURL?.path { let userDefaults = UserDefaults.standard let typeData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false) userDefaults.set(typeData, forKey: "KMNoteOutlineFilterSelectArray_Type" + _key) let colorData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false) userDefaults.set(colorData, forKey: "KMNoteOutlineFilterSelectArray_Color" + _key) let authorData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false) userDefaults.set(authorData, forKey: "KMNoteOutlineFilterSelectArray_Author" + _key) userDefaults.synchronize() } } func clearNotification() { } } // MARK: - Analytics (埋点) extension KMLeftSideViewController { func trackEvent(type: BotaType) -> Void { if (type == .Thumbnail) { KMAnalytics.trackEvent(eventName: "Btn_LeftSideBar_Thumbnail", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.leftSideBar, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.leftSideBar_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .Outline) { KMAnalytics.trackEvent(eventName: "Btn_LeftSideBar_Outline", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.leftSideBar, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.leftSideBar_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .BookMark) { KMAnalytics.trackEvent(eventName: "Btn_LeftSideBar_BookMark", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.leftSideBar, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.leftSideBar_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .Annotation) { KMAnalytics.trackEvent(eventName: "Btn_LeftSideBar_Annotation", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.leftSideBar, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.leftSideBar_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .Search) { KMAnalytics.trackEvent(eventName: "Btn_LeftSideBar_Search", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.leftSideBar, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.leftSideBar_Btn], platform: .AppCenter, appTarget: .all) } } } // MARK: - Private Methods extension KMLeftSideViewController { @objc private func _themeChanged(_ notification: NSNotification) { DispatchQueue.main.asyncAfter(deadline: .now()+0.3) { self._updateViewColor() } } private func _updateViewColor() { if(KMAppearance.isDarkMode()){ self.leftListView.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor self.snapshotNormalView.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor self.thumbnailView.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor self.noteView.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor self.outlineView.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor self.view.layer?.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1).cgColor self.thumbnailTableView.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1) self.groupedFindTableView.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1) self.tocOutlineView.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1) self.findTableView.backgroundColor = NSColor(red: 0.149, green: 0.157, blue: 0.169, alpha: 1) self.snapshotSearchField.layer?.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1).cgColor self.outlineSearchField.layer?.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1).cgColor self.noteSearchField.layer?.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1).cgColor self.segmentedControl.layer?.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1).cgColor self.snapshotSearchField.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1) self.outlineSearchField.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1) self.noteSearchField.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1) } else { self.leftListView.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1, alpha: 1).cgColor self.snapshotNormalView.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1, alpha: 1).cgColor self.thumbnailView.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1, alpha: 1).cgColor self.noteView.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1, alpha: 1).cgColor self.outlineView.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1, alpha: 1).cgColor self.view.layer?.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1, alpha: 1).cgColor self.thumbnailTableView.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1.000, alpha: 1) self.groupedFindTableView.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1.000, alpha: 1) self.tocOutlineView.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1.000, alpha: 1) self.findTableView.backgroundColor = NSColor(red: 0.988, green: 0.992, blue: 1.000, alpha: 1) self.snapshotSearchField.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor self.outlineSearchField.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor self.noteSearchField.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor self.segmentedControl.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor self.snapshotSearchField.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1) self.outlineSearchField.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1) self.noteSearchField.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1) } } private func _hasContainString(_ searchString: String, rootOutline outline: CPDFOutline) -> Bool { let label_low = outline.label.lowercased() let searchString_low = searchString.lowercased() if label_low.contains(searchString_low) { // if ([outline.label rangeOfString:searchString options:self.outlineIgnoreCaseFlag?NSCaseInsensitiveSearch:0].location != NSNotFound){ return true } else { var subHas = false for i in 0 ..< outline.numberOfChildren { if let subOutline = outline.child(at: i) { subHas = self._hasContainString(searchString, rootOutline: subOutline) } else { continue } if (subHas) { break } } return subHas } return false } } // MARK: - NSTableViewDelegate, NSTableViewDataSource extension KMLeftSideViewController: NSTableViewDelegate, NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { if tableView.isEqual(to: self.thumbnailTableView) { return self.thumbnails.count } else if tableView.isEqual(to: self.findTableView) { return self.searchResults.count } else if tableView.isEqual(to: self.groupedFindTableView) { return self.groupSearchResults.count } return 0 } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { if tableView.isEqual(to: self.thumbnailTableView) { let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMThumbnailTableviewCell"), owner: self) as! KMThumbnailTableviewCell let thumbnail = self.thumbnails[row] cell.pageNumLabel.stringValue = thumbnail.label // cell.thumImage.image = thumbnail.image cell.pageView.page = self.listView.document.page(at: UInt(row)) if let _image = thumbnail.image { let multiplierHToW = _image.size.height / (_image.size.width == 0 ? 1 : _image.size.width) let multiplierWToH = _image.size.width / (_image.size.height == 0 ? 1 : _image.size.height) if (_image.size.height > _image.size.width) { NSLayoutConstraint.deactivate([cell.imageAspectRatioLayout]) // cell.imageAspectRatioLayout = NSLayoutConstraint(item: cell.thumImage, attribute: .height, relatedBy: .equal, toItem: cell.thumImage, attribute: .width, multiplier: multiplierHToW, constant: 0) // NSLayoutConstraint.activate([cell.imageAspectRatioLayout]) } else { NSLayoutConstraint.deactivate([cell.imageAspectRatioLayout]) // cell.imageAspectRatioLayout = NSLayoutConstraint(item: cell.thumImage, attribute: .width, relatedBy: .equal, toItem: cell.thumImage, attribute: .height, multiplier: multiplierWToH, constant: 0) // NSLayoutConstraint.activate([cell.imageAspectRatioLayout]) } } if (self.isDisplayPageSize) { cell.sizeLabel.isHidden = false //获取Page的真实尺寸 let page = self.listView.document.page(at: UInt(row)) let rect = page?.bounds(for: .cropBox) ?? .zero let w = KMPageSizeTool.conversion(withUnit: "mm", value: (CGRectGetWidth(rect)/595 * 210)) let h = KMPageSizeTool.conversion(withUnit: "mm", value: (CGRectGetHeight(rect)/842 * 297)) if let data = page?.rotation, data == 90 || data == 270 { cell.sizeLabel.stringValue = String(format: "%.f × %.f %@", h.stringToCGFloat(), w.stringToCGFloat(), KMLocalizedString("mm", nil)) } else { cell.sizeLabel.stringValue = String(format: "%.f × %.f %@", w.stringToCGFloat(), h.stringToCGFloat(), KMLocalizedString("mm", nil)) } } else { cell.sizeLabel.isHidden = true } cell.sizeTopConstant.constant = cell.sizeLabel.isHidden ? -cell.sizeLabel.frame.size.height : 0 if(self.thumbnailTableView.selectedRowIndexes.contains(row)) { cell.isSelectCell = true } else { cell.isSelectCell = false } return cell } else if (tableView.isEqual(to: self.findTableView)) { let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMFindTableviewCell"), owner: self) as! KMFindTableviewCell let selection = searchResults[row] if let data = tableColumn?.identifier.rawValue, data == "results" { cell.resultLabel.attributedStringValue = selection.attributedString cell.resultLabel.textColor = KMAppearance.Layout.h0Color() } else if let data = tableColumn?.identifier.rawValue, data == "page" { cell.resultLabel.stringValue = "\(Int(selection.selection.page?.pageIndex() ?? 0) + 1)" cell.resultLabel.textColor = KMAppearance.Layout.h2Color() } return cell } else if tableView.isEqual(to: self.snapshotTableView) { let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMSnapshotTableViewCell"), owner: self) as! KMSnapshotTableViewCell // SKSnapshotWindowController *snapshot = snapshots[row]; // cell.snapshotImage.image = snapshot.thumbnail; // cell.snapshotLabel.stringValue = snapshot.pageLabel; // if (snapshot.hasWindow) { // cell.snapshotImageView.hidden = NO; // } else { // cell.snapshotImageView.hidden = YES; // } // if(selectCellList.count > 0 && [selectCellList.firstObject integerValue]< 0 && (NSUInteger)row == self.snapshots.count - 1) { // cell.isSelectCell = YES; // } else { // cell.isSelectCell = NO; // } // for (NSUInteger i = 0; i < selectCellList.count; i ++) { // NSInteger selectCell = [selectCellList[i] integerValue]; // if (selectCell == row) { // cell.isSelectCell = YES; // } // } // if (row == tableView.selectedRow) { // [cell.snapshotImageView setImage:[NSImage imageNamed:KMImageNameUXIconSidebarSnapshotWindowSel]]; // } else { // [cell.snapshotImageView setImage:[NSImage imageNamed:KMImageNameUXIconSidebarSnapshotWindowNor]]; // } return cell } return nil } func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { if tableView.isEqual(to: self.thumbnailTableView) { let scaling = UserDefaults.standard.float(forKey: "KMThumbnailSizeScalingKey") // let thumbnailSize = self.thumbnails[row].size let thumbnailSize = NSMakeSize(self.thumbnailCacheSize, self.thumbnailCacheSize) let newScaling: CGFloat = scaling.cgFloat + 0.1 let newThumbnailHeight = thumbnailSize.width * newScaling if (newThumbnailHeight > MIN_SIDE_PANE_WIDTH) { self.thumbnailZoomOutButton.isEnabled = false } else { self.thumbnailZoomOutButton.isEnabled = true } if ((scaling - 0.1) < 0.3) { self.thumbnailZoomInButton.isEnabled = false } else { self.thumbnailZoomInButton.isEnabled = true } var labelHeight = 0.0 if (self.isDisplayPageSize) { labelHeight = 56.0 } else { labelHeight = 41.5 } let cellHeight = thumbnailSize.height + labelHeight var thumbSize: NSSize = .zero if (scaling != nil && scaling > 0) { thumbSize = NSMakeSize(thumbnailSize.width * scaling.cgFloat, cellHeight * scaling.cgFloat) } else { thumbSize = NSMakeSize(thumbnailSize.width, cellHeight) } return thumbSize.height // NSSize cellSize = NSMakeSize([[tv tableColumnWithIdentifier:IMAGE_COLUMNID] width], fmin(thumbSize.height, roundedThumbnailSize)); // if (thumbSize.height < [tv rowHeight]) // return [tv rowHeight]; // else if (thumbSize.width / thumbSize.height < cellSize.width / cellSize.height) // return cellSize.height; // else // return fmax([tv rowHeight], fmin(cellSize.width, thumbSize.width) * thumbSize.height / thumbSize.width); } else if tableView.isEqual(to: self.snapshotTableView) { let scaling = UserDefaults.standard.float(forKey: "KMSnapshotSizeScalingKey") // NSSize snapshotSize = [[[[rightSideController.snapshotArrayController arrangedObjects] objectAtIndex:row] thumbnail] size]; let snapshotSize = CGSizeMake(120, 63) var newScaling = scaling + 0.1 let newSnapshotHeight = snapshotSize.width * newScaling.cgFloat; if (newSnapshotHeight > MIN_SIDE_PANE_WIDTH) { self.snapshotNormalZoomInButton.isEnabled = false } else { self.snapshotNormalZoomInButton.isEnabled = true } if ((scaling - 0.1) < 0.3 || (newSnapshotHeight < 150.0)) { self.snapshotNormalZoomOutButton.isEnabled = false } else { self.snapshotNormalZoomOutButton.isEnabled = true } let cellHeight = snapshotSize.height + 24.0 var thumbSize: NSSize = .zero if (scaling > 0) { thumbSize = NSMakeSize(snapshotSize.width * scaling.cgFloat, cellHeight * scaling.cgFloat) } else { thumbSize = NSMakeSize(snapshotSize.width, cellHeight) } return thumbSize.height } else if (tableView.isEqual(to: self.findTableView)) { return 40.0 } else if tableView.isEqual(to: self.groupedFindTableView) { return 16 } return tableView.rowHeight } func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { if (tableView.isEqual(to: self.findTableView)) { let rowView = KMBotaTableRowView() return rowView } else if tableView.isEqual(to: self.groupedFindTableView) { let rowView = KMGroupFindTableRowView() rowView.totalNumber = self.groupSearchResults.first?.datas.count ?? 0 let model = self.groupSearchResults[row] rowView.number = model.datas.count rowView.pageIndex = Int(model.selectionPageIndex) + 1 return rowView } return nil } func tableViewSelectionIsChanging(_ notification: Notification) { } func tableViewSelectionDidChange(_ notification: Notification) { // if ([[aNotification object] isEqual:leftSideController.findTableView] || [[aNotification object] isEqual:leftSideController.groupedFindTableView]) { // [self updateFindResultHighlightsForDirection:NSDirectSelection]; // // if ([self interactionMode] == SKPresentationMode && [[NSUserDefaults standardUserDefaults] boolForKey:SKAutoHidePresentationContentsKey]) // [self hideLeftSideWindow]; // } else if self.findTableView.isEqual(to: notification.object) { let row = self.findTableView.selectedRow if row >= 0 { let model = self.searchResults[row] if model.selection != nil { self.listView.go(to: model.selection, animated: true) self.listView.setHighlightedSelection(model.selection, animated: true) self.listView.setNeedsDisplayAnnotationViewForVisiblePages() } } } else if self.thumbnailTableView.isEqual(to: notification.object) { // if (mwcFlags.updatingThumbnailSelection == 0) { let row = self.thumbnailTableView.selectedRow let curPage = self.listView.document.index(for: self.listView.currentPage()) if (row != -1 && row != curPage) { // [pdfView goToPage:[[pdfView document] pageAtIndex:row]]; self.listView.go(toPageIndex: row, animated: true) } // if ([self interactionMode] == SKPresentationMode && [[NSUserDefaults standardUserDefaults] boolForKey:SKAutoHidePresentationContentsKey]) // [self hideLeftSideWindow]; // thumbnailSelectCount = row; // var rowIndexSet = IndexSet() // for i in 0 ..< self.thumbnailTableView.numberOfRows { // rowIndexSet.insert(i) // } // self.thumbnailTableView.reloadData(forRowIndexes: rowIndexSet, columnIndexes: IndexSet(integer: 0)) // } let view = self.thumbnailTableView.view(atColumn: 0, row: self.preThumbnailRow, makeIfNecessary: false) as? KMThumbnailTableviewCell view?.isSelectCell = false let view2 = self.thumbnailTableView.view(atColumn: 0, row: row, makeIfNecessary: false) as? KMThumbnailTableviewCell view2?.isSelectCell = true self.preThumbnailRow = row } // else if ([[aNotification object] isEqual:rightSideController.snapshotTableView]) { // NSInteger row = [rightSideController.snapshotTableView selectedRow]; // [selectCellList removeAllObjects]; // [selectCellList addObject:[NSString stringWithFormat:@"%ld",row]]; // if (row != -1) { // SKSnapshotWindowController *controller = [[rightSideController.snapshotArrayController arrangedObjects] objectAtIndex:row]; // if ([[controller window] isVisible]) // [[controller window] orderFront:self]; // } // NSMutableIndexSet *rowIndexSet = [[[NSMutableIndexSet alloc] init] autorelease]; // for (NSInteger i = 0; i < rightSideController.snapshotTableView.numberOfRows; i ++) { // [rowIndexSet addIndex:i]; // } // NSMutableIndexSet *columnIndexSet = [[[NSMutableIndexSet alloc] init] autorelease]; // [columnIndexSet addIndex:0]; // [rightSideController.snapshotTableView reloadDataForRowIndexes:rowIndexSet columnIndexes:columnIndexSet]; // // } } func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation { if dropOperation == .on || tableView.isEqual(to: self.thumbnailTableView) == false { return NSDragOperation(rawValue: 0) } let pboard = info.draggingPasteboard if (pboard.availableType(from: [.localDraggedTypes]) != nil) { return .move } else if (pboard.availableType(from: [.fileURL]) != nil) && tableView.isEqual(to: self.thumbnailTableView) { guard let pbItems = pboard.pasteboardItems else { return NSDragOperation(rawValue: 0) } // guard let _allowedFileTypes = self.kmAllowedFileTypes else { // return .generic // } var hasValidFile = false for item in pbItems { guard let data = item.string(forType: .fileURL), let _url = URL(string: data) else { continue } let type = _url.pathExtension.lowercased() // if (_allowedFileTypes.contains(type)) { hasValidFile = true // break // } } if (!hasValidFile) { return NSDragOperation(rawValue: 0) } } return NSDragOperation(rawValue: 0) } func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool { var result = false if tableView.isEqual(to: self.thumbnailTableView) == false { return result } // let pasteboard = info.draggingPasteboard // // if pasteboard.availableType(from: [.localDraggedTypes]) { // result = true // let rowData = pasteboard.data(forType: .localDraggedTypes) // let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: rowData!) // NSData *urlData = [pasteboard dataForType:KPDFThumbnailDoucumentURLForDraggedTypes]; // NSString *url = [NSKeyedUnarchiver unarchiveObjectWithData:urlData]; // if(![url isEqualToString:[pdfView document].documentURL.absoluteString] && url) { // if ([pasteboard availableTypeFromArray:[NSArray arrayWithObject:NSFilenamesPboardType]]){ // NSArray *fileNames = [pasteboard propertyListForType:NSFilenamesPboardType]; // if (fileNames.count == 1) { // NSString *path = fileNames.firstObject; // NSString *pathExtension = [path.pathExtension lowercaseString]; // if ([pathExtension isEqualToString:@"pdf"]) { // __block NSInteger index = row; // __block NSMutableIndexSet *insertIndexSet = [[[NSMutableIndexSet alloc] init] autorelease]; // PDFDocument *pdf = [[[PDFDocument alloc] initWithURL:[NSURL fileURLWithPath:path]] autorelease]; // if ([pdf isEncrypted]) { // KMDecryptWindowController *vc = [[KMDecryptWindowController alloc] init]; // vc.filePath = url; // [vc beginSheetModalForWindow:self.window completionHandler:^(NSString *password) { // if (password) { // [pdf unlockWithPassword:password]; // for(NSUInteger i=0; i Bool { if tableView.isEqual(to: self.thumbnailTableView) { // let idx = rowIndexes.first // if (idx != NSNotFound && [[pdfView document] isLocked] == NO) { // PDFPage *page = [[pdfView document] pageAtIndex:idx]; // NSString *fileExt = nil; // NSData *tiffData = [page TIFFDataForRect:[page boundsForBox:[pdfView displayBox]]]; // // if ([[pdfView document] allowsPrinting]) { // NSData *pdfData = [page dataRepresentation]; // fileExt = @"pdf"; // [pboard declareTypes:[NSArray arrayWithObjects:NSPasteboardTypePDF, NSPasteboardTypeTIFF,NSFilenamesPboardType, NSFilesPromisePboardType, KPDFThumbnailLocalForDraggedTypes,KPDFThumbnailDoucumentURLForDraggedTypes,nil] owner:self]; // [pboard setData:pdfData forType:NSPasteboardTypePDF]; // NSData *zNSIndexSetData = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes]; // [pboard setData:zNSIndexSetData forType:KPDFThumbnailLocalForDraggedTypes]; // NSData *documentURL = [NSKeyedArchiver archivedDataWithRootObject:[[pdfView document].documentURL absoluteString]]; // NSString *docmentName = [[[pdfView.document.documentURL path] lastPathComponent] stringByDeletingPathExtension]; // __block NSMutableString *pagesName = nil; // if (rowIndexes.count > 1) { // pagesName = [NSMutableString stringWithString:@" pages"]; // // } else { // pagesName = [NSMutableString stringWithString:@" page"]; // // } // NSString * tFileName = [NSString stringWithFormat:@"%@ %@",pagesName,[self fileNameWithSelectedPages:rowIndexes]]; // PDFDocument * pdf = [[[PDFDocument alloc] init] autorelease]; // [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { // PDFPage *copyPage = [[pdfView.document pageAtIndex:idx] copy]; // [pdf insertPage:copyPage atIndex:pdf.pageCount]; // [copyPage release]; // }]; // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); // NSString *cachesDir = [paths objectAtIndex:0]; // docmentName = [NSString stringWithFormat:@"%@%@",docmentName,tFileName]; // if (docmentName.length > 50) { // [docmentName substringWithRange:NSMakeRange(0, 50)]; // } // cachesDir = [[cachesDir stringByAppendingPathComponent:docmentName] stringByAppendingPathExtension:@"pdf"]; // // BOOL success = [pdf writeToFile:cachesDir]; // if (success) { // [pboard setPropertyList:@[cachesDir] forType:NSFilenamesPboardType]; // }else{ // [pboard setPropertyList:@[@""] forType:NSFilenamesPboardType]; // } // [pboard setData:documentURL forType:KPDFThumbnailDoucumentURLForDraggedTypes]; // } else { // fileExt = @"tiff"; // [pboard declareTypes:[NSArray arrayWithObjects:NSPasteboardTypeTIFF, NSFilesPromisePboardType, nil] owner:self]; // } // [pboard setData:tiffData forType:NSPasteboardTypeTIFF]; // [pboard setPropertyList:[NSArray arrayWithObject:fileExt] forType:NSFilesPromisePboardType]; let data: Data = try! NSKeyedArchiver.archivedData(withRootObject: rowIndexes, requiringSecureCoding: true) pboard.declareTypes([.localDraggedTypes], owner: self) pboard.setData(data, forType: .localDraggedTypes) return true // } } // else if ([tv isEqual:rightSideController.snapshotTableView]) { // NSUInteger idx = [rowIndexes firstIndex]; // if (idx != NSNotFound) { // SKSnapshotWindowController *snapshot = [self objectInSnapshotsAtIndex:idx]; // [pboard declareTypes:[NSArray arrayWithObjects:NSPasteboardTypeTIFF, NSFilesPromisePboardType, nil] owner:self]; // [pboard setData:[[snapshot thumbnailWithSize:0.0] TIFFRepresentation] forType:NSPasteboardTypeTIFF]; // [pboard setPropertyList:[NSArray arrayWithObject:@"tiff"] forType:NSFilesPromisePboardType]; // return YES; // } // } return false } /* #pragma mark dragging - (NSArray *)tableView:(NSTableView *)tv namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes { if ([tv isEqual:leftSideController.thumbnailTableView]) { __block NSMutableArray *fileURLArray = [NSMutableArray array]; if (rowIndexes.count > 1) { NSString *docmentName = @""; NSString * tFileName = [NSString stringWithFormat:@"%@",[self fileNameWithSelectedPages:rowIndexes]]; PDFDocument *pdf = [[[PDFDocument alloc] init] autorelease]; [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { if (idx != NSNotFound && [[pdfView document] isLocked] == NO) { PDFPage *copyPage = [[[pdfView document] pageAtIndex:idx] copy]; [pdf insertPage:copyPage atIndex:pdf.pageCount]; [copyPage release]; } }]; NSURL *fileURL = [[[dropDestination URLByAppendingPathComponent:tFileName] URLByAppendingPathExtension:@"pdf"] uniqueFileURL]; docmentName = fileURL.path; BOOL success = [pdf writeToFile:docmentName]; if(success) { [fileURLArray addObject:[fileURL lastPathComponent]]; } } else { PDFPage *page = [[pdfView document] pageAtIndex:rowIndexes.firstIndex]; NSURL *fileURL = [dropDestination URLByAppendingPathComponent:[self draggedFileNameForPage:page]]; NSString *pathExt = nil; NSData *data = nil; if ([[pdfView document] allowsPrinting]) { pathExt = @"pdf"; data = [page dataRepresentation]; } else { pathExt = @"tiff"; data = [page TIFFDataForRect:[page boundsForBox:[pdfView displayBox]]]; } fileURL = [[fileURL URLByAppendingPathExtension:pathExt] uniqueFileURL]; if ([data writeToURL:fileURL atomically:YES]) { [fileURLArray addObject:[fileURL lastPathComponent]]; } } return fileURLArray; } else if ([tv isEqual:rightSideController.snapshotTableView]) { NSUInteger idx = [rowIndexes firstIndex]; if (idx != NSNotFound) { SKSnapshotWindowController *snapshot = [self objectInSnapshotsAtIndex:idx]; PDFPage *page = [[pdfView document] pageAtIndex:[snapshot pageIndex]]; NSURL *fileURL = [[dropDestination URLByAppendingPathComponent:[self draggedFileNameForPage:page]] URLByAppendingPathExtension:@"tiff"]; fileURL = [fileURL uniqueFileURL]; if ([[[snapshot thumbnailWithSize:0.0] TIFFRepresentation] writeToURL:fileURL atomically:YES]) return [NSArray arrayWithObjects:[fileURL lastPathComponent], nil]; } } return [NSArray array]; } - (void)tableView:(NSTableView *)tv sortDescriptorsDidChange:(NSArray *)oldDescriptors { if ([tv isEqual:leftSideController.groupedFindTableView]) { [leftSideController.groupedFindArrayController setSortDescriptors:[tv sortDescriptors]]; } } #pragma mark NSTableView delegate protocol - (void)tableViewColumnDidResize:(NSNotification *)aNotification { if ([[[[aNotification userInfo] objectForKey:@"NSTableColumn"] identifier] isEqualToString:IMAGE_COLUMNID]) { if ([[aNotification object] isEqual:leftSideController.thumbnailTableView]) { [leftSideController.thumbnailTableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [leftSideController.thumbnailTableView numberOfRows])]]; } else if ([[aNotification object] isEqual:rightSideController.snapshotTableView]) { [rightSideController.snapshotTableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [rightSideController.snapshotTableView numberOfRows])]]; } } } - (void)tableView:(NSTableView *)tv deleteRowsWithIndexes:(NSIndexSet *)rowIndexes { if (![[IAPProductsManager defaultManager] isAvailableAllFunction]) { [[KMPurchaseCompareWindowController sharedInstance] showWindow:nil]; return; } if ([tv isEqual:rightSideController.snapshotTableView]) { NSArray *controllers = [[rightSideController.snapshotArrayController arrangedObjects] objectsAtIndexes:rowIndexes]; [controllers makeObjectsPerformSelector:@selector(close)]; } else if ([tv isEqual:leftSideController.thumbnailTableView]) { [rowIndexes enumerateIndexesWithOptions:NSEnumerationReverse usingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { if (idx >= [[pdfView document] pageCount]) { return; } for (PDFAnnotation *item in [[[pdfView document] pageAtIndex:idx] notes]){ [pdfView removeAnnotation:item]; } PDFPage *page = [[pdfView document] pageAtIndex:idx]; [[[[self document] undoManager] prepareWithInvocationTarget:self] insertPage:page pageAtIndex:idx]; [[pdfView document] removePageAtIndex:idx]; }]; [pdfView layoutDocumentView]; [pageLabels setArray:[[pdfView document] pageLabels]]; [self resetThumbnails]; NSUInteger idx = [rowIndexes firstIndex]; NSInteger index = MIN(idx, [[pdfView document] pageCount]-1); [pdfView goToPage:[[pdfView document] pageAtIndex:index]]; } } - (void)insertPage:(PDFPage*)page pageAtIndex:(NSInteger)index { [[[[self document] undoManager] prepareWithInvocationTarget:self] tableView:leftSideController.thumbnailTableView deleteRowsWithIndexes:[NSIndexSet indexSetWithIndex:index]]; [[pdfView document] insertPage:page atIndex:index]; [pdfView layoutDocumentView]; [pageLabels setArray:[[pdfView document] pageLabels]]; [self resetThumbnails]; NSInteger pageIndex = MIN((NSUInteger)index, [[pdfView document] pageCount]-1); [pdfView goToPage:[[pdfView document] pageAtIndex:pageIndex]]; } - (void)tableView:(NSTableView *)tv copyRowsWithIndexes:(NSIndexSet *)rowIndexes { if (![IAPProductsManager defaultManager].isAvailableAllFunction) { [[KMPurchaseCompareWindowController sharedInstance] showWindow:nil]; return; } if ([tv isEqual:leftSideController.thumbnailTableView]) { self.copysPages = [NSMutableArray array]; if ([[pdfView document] isLocked] == NO) { [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { PDFPage *page = [[pdfView document] pageAtIndex:idx]; [self.copysPages addObject:page]; }]; // NSData *tiffData = [page TIFFDataForRect:[page boundsForBox:[pdfView displayBox]]]; // NSPasteboard *pboard = [NSPasteboard generalPasteboard]; // NSPasteboardItem *pboardItem = [[[NSPasteboardItem alloc] init] autorelease]; // if ([[pdfView document] allowsPrinting]) // [pboardItem setData:[page dataRepresentation] forType:NSPasteboardTypePDF]; // [pboardItem setData:tiffData forType:NSPasteboardTypeTIFF]; // [pboard clearContents]; // [pboard writeObjects:[NSArray arrayWithObjects:pboardItem, nil]]; } } else if ([tv isEqual:leftSideController.findTableView]) { NSMutableString *string = [NSMutableString string]; [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { PDFSelection *match = [searchResults objectAtIndex:idx]; [string appendString:@"* "]; [string appendFormat:NSLocalizedString(@"Page %@", @""), [match firstPageLabel]]; [string appendFormat:@": %@\n", [[match contextString] string]]; }]; NSPasteboard *pboard = [NSPasteboard generalPasteboard]; [pboard clearContents]; [pboard writeObjects:[NSArray arrayWithObjects:string, nil]]; } else if ([tv isEqual:leftSideController.groupedFindTableView]) { NSMutableString *string = [NSMutableString string]; [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { SKGroupedSearchResult *result = [groupedSearchResults objectAtIndex:idx]; NSArray *matches = [result matches]; [string appendString:@"* "]; [string appendFormat:NSLocalizedString(@"Page %@", @""), [[result page] displayLabel]]; [string appendString:@": "]; [string appendFormat:NSLocalizedString(@"%ld Results", @""), (long)[matches count]]; [string appendFormat:@":\n\t%@\n", [[matches valueForKeyPath:@"contextString.string"] componentsJoinedByString:@"\n\t"]]; }]; NSPasteboard *pboard = [NSPasteboard generalPasteboard]; [pboard clearContents]; [pboard writeObjects:[NSArray arrayWithObjects:string, nil]]; } } - (void)tableView:(NSTableView *)tv rotateRowsWithIndexes:(NSIndexSet *)rowIndexes { if ([tv isEqual:leftSideController.thumbnailTableView]) { [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { if (idx != NSNotFound) { PDFPage *page = [[pdfView document] pageAtIndex:idx]; [[[[self document] undoManager] prepareWithInvocationTarget:self] rotatePage:page pageAtIndex:idx]; if (page.rotation == 0) { [page setRotation:90]; } else if (page.rotation == 90){ [page setRotation:180]; } else if (page.rotation == 180){ [page setRotation:270]; } else if (page.rotation == 270){ [page setRotation:0]; } [pdfView layoutDocumentView]; [self resetThumbnails]; NSInteger pageIndex = MIN(idx, [[pdfView document] pageCount]-1); [pdfView goToPage:[[pdfView document] pageAtIndex:pageIndex]]; } [leftSideController.thumbnailTableView selectRowIndexes:rowIndexes byExtendingSelection:YES]; }]; } } - (void)rotatePage:(PDFPage*)page pageAtIndex:(NSInteger)index { [[[[self document] undoManager] prepareWithInvocationTarget:self] tableView:leftSideController.thumbnailTableView rotateRowsWithIndexes:[NSIndexSet indexSetWithIndex:index]]; if (page.rotation == 0) { [page setRotation:270]; } else if (page.rotation == 90){ [page setRotation:0]; } else if (page.rotation == 180){ [page setRotation:90]; } else if (page.rotation == 270){ [page setRotation:180]; } [pdfView layoutDocumentView]; [self resetThumbnails]; } - (void)tableView:(NSTableView *)tv shareRowsWithIndexes:(NSIndexSet *)rowIndexes { if ([tv isEqual:leftSideController.thumbnailTableView]) { NSUInteger idx = [rowIndexes firstIndex]; if (idx != NSNotFound) { PDFPage *page = [[pdfView document] pageAtIndex:idx]; NSString *fileName = [[[pdfView document] documentURL] lastPathComponent]; NSString *folderPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *filePath = [folderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"Untitled"]]; filePath = [filePath stringByAppendingPathExtension:[fileName pathExtension]]; [self fileWithPage:page atPath:filePath]; if (rint(NSAppKitVersionNumber) < NSAppKitVersionNumber10_8) { [KMMailHelper sendFileWithPaths:[NSArray arrayWithObject:filePath]]; } else { NSSharingService *service = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeEmail]; [service performWithItems:[NSArray arrayWithObject:[NSURL fileURLWithPath:filePath]]]; } } } } - (void)tableView:(NSTableView *)tv extractRowsWithIndexes:(NSIndexSet *)rowIndexes { if ([tv isEqual:leftSideController.thumbnailTableView]) { NSMutableArray *pages = [NSMutableArray array]; [leftSideController.thumbnailTableView.selectedRowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { if (idx < self.pdfView.document.pageCount) { [pages addObject:[self.pdfView.document pageAtIndex:idx]]; } }]; NSString * fileName = [self.pdfView.document getFileNameAccordingSelctPages:pages]; KMSavePanelAccessoryController *saveAccessCtr = [[KMSavePanelAccessoryController alloc] init]; NSSavePanel * outputSavePanel = [NSSavePanel savePanel]; [outputSavePanel setAllowedFileTypes:[NSArray arrayWithObject:@"pdf"]]; outputSavePanel.accessoryView = saveAccessCtr.view; [outputSavePanel setNameFieldStringValue:fileName]; [outputSavePanel beginSheetModalForWindow:[self window]completionHandler:^(NSInteger result) { if (result == NSModalResponseOK) { [saveAccessCtr retain]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ KMProgressWindowController * vc = [[[KMProgressWindowController alloc] init] autorelease]; // [NSApp beginSheet:[vc window] // modalForWindow:self.window // modalDelegate:nil // didEndSelector:nil // contextInfo:NULL]; [self.window beginSheet:[vc window] completionHandler:^(NSModalResponse returnCode) { }]; NSString *saveFilePath = [[outputSavePanel URL] path]; dispatch_async(dispatch_get_global_queue(0, 0), ^{ PDFDocument * pdf = [[[PDFDocument alloc] init] autorelease]; BOOL success = [pdf extractAsOneDocumentWithPages:pages savePath:saveFilePath]; dispatch_async(dispatch_get_main_queue(), ^{ if (success) { if (saveAccessCtr.openAutomaticButton.state == NSControlStateValueOn) { [[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:[outputSavePanel URL] display:YES completionHandler:^(NSDocument * _Nullable document, BOOL documentWasAlreadyOpen, NSError * _Nullable error) { }]; } else { NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; NSURL *url = [NSURL fileURLWithPath:saveFilePath]; [workspace activateFileViewerSelectingURLs:[NSArray arrayWithObject:url]]; } } [NSApp endSheet:vc.window]; [vc close]; [saveAccessCtr release]; }); }); }); } [saveAccessCtr release]; }]; } } - (void)fileWithPage:(PDFPage *)page atPath:(NSString *)filePath { NSData *data = [page dataRepresentation]; PDFDocument *document = [[PDFDocument alloc] initWithData:data]; [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; BOOL success = [document writeToURL:[NSURL fileURLWithPath:filePath]]; if (success) { NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; NSURL *url = [NSURL fileURLWithPath:filePath]; [workspace activateFileViewerSelectingURLs:[NSArray arrayWithObject:url]]; } [document release]; */ } // MARK: - NSOutlineViewDelegate, NSOutlineViewDataSource /* func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { if item is KMBOTAAnnotationSection { let section = item as? KMBOTAAnnotationSection return section!.annotations?[index] as Any } else if item is KMBOTAAnnotationItem { return item as Any } else { var tempArray: [KMBOTAAnnotationSection] = [] for temp in self.data { if temp.annotations?.count != 0 { tempArray.append(temp) } } let section = tempArray[index] return section as Any } } func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { if item is KMBOTAAnnotationItem { let cell : KMAnnotationOutlineCellView = KMAnnotationOutlineCellView.init() cell.delegate = self cell.model = item as? KMBOTAAnnotationItem return cell } else if item is KMBOTAAnnotationSection { let section = item as? KMBOTAAnnotationSection let cell : KMAnnotationOutlineSectionView = KMAnnotationOutlineSectionView.init() cell.model = section return cell } return NSTableCellView() } func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? { let rowView = KMAnnotationOutlineRowView() if item is KMBOTAAnnotationItem { rowView.model = (item as? KMBOTAAnnotationItem) } else if item is KMBOTAAnnotationSection { rowView.section = (item as? KMBOTAAnnotationSection) } rowView.mouseDownAction = { [unowned self] view, event in if rowView.section != nil { let expanded = outlineView.isItemExpanded(outlineView.item(atRow: outlineView.selectedRow)) if expanded { outlineView.collapseItem(outlineView.item(atRow: outlineView.selectedRow), collapseChildren: true) outlineView.reloadItem(outlineView.item(atRow: outlineView.selectedRow)) } else { outlineView.expandItem(outlineView.item(atRow: outlineView.selectedRow), expandChildren: true) outlineView.reloadItem(outlineView.item(atRow: outlineView.selectedRow)) } } else if rowView.model != nil { self.didSelectItem(view: rowView, event: event) } } rowView.rightMouseDownAction = { [unowned self] view, event in if rowView.section != nil { } else if rowView.model != nil { if !KMOCToolClass.arrayContains(array: self.selectItems, annotation: item) || self.selectItems.count == 1 { self.selectItem(item: item as! KMBOTAAnnotationItem) } DispatchQueue.main.async { self.delegate?.annotationOutlineView(self, rightMouseDownDidSelectView: view, evnet: event) } } } rowView.hoverCallback = { [unowned self] (mouseEntered, mouseBox) in self.outlineView.enumerateAvailableRowViews { view, row in if view is KMAnnotationOutlineRowView { (view as? KMAnnotationOutlineRowView)?.model?.hover = false (view as? KMAnnotationOutlineRowView)?.reloadData() } } if mouseEntered { rowView.model?.hover = true } else { rowView.model?.hover = false } } return rowView } func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat { if item is KMBOTAAnnotationItem { return KMBOTAAnnotationTool.fetchCellHeight(annotation: (item as? KMBOTAAnnotationItem)!.annotation!, maxSize: CGSize(width: self.maxWidth - 16, height: 1000)) } else if item is KMBOTAAnnotationSection { return 40 } else { return 30 } } func outlineViewSelectionDidChange(_ notification: Notification) { if self.outlineView.selectedRow == -1 { self.cancelSelect() } } func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { if item is KMBOTAAnnotationItem { return false } else if item is KMBOTAAnnotationSection { let section = item as? KMBOTAAnnotationSection return section!.annotations?.count ?? 0 > 0 } return false } func outlineView(_ outlineView: NSOutlineView, shouldExpandItem item: Any) -> Bool { if let item = item as? KMBOTAAnnotationSection { if !item.isItemExpanded { item.isItemExpanded = true outlineView.animator().expandItem(item, expandChildren: true) return false } } return true } func outlineView(_ outlineView: NSOutlineView, shouldCollapseItem item: Any) -> Bool { if let item = item as? KMBOTAAnnotationSection { if item.isItemExpanded { item.isItemExpanded = false outlineView.animator().collapseItem(item, collapseChildren: true) return false } } return true } */ extension KMLeftSideViewController: NSOutlineViewDelegate, NSOutlineViewDataSource { func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { if outlineView.isEqual(to: self.tocOutlineView) { let isLocked = self.listView.document?.isLocked ?? true if isLocked { // 文档不存在 或 已加锁 return 0 } if item == nil { // 第一层 // 获取根 guard let outline = self.listView.document.outlineRoot() else { return 0 } if outline.numberOfChildren == 0 { return 0 } if self.isSearchOutlineMode { // 是否为搜索模块 if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: outline) { self.showSearchOutlineBlankState(false) } else { self.showSearchOutlineBlankState(true) return 0 } } else { if outline.numberOfChildren > 0 { // 有数据 self.leftSideEmptyVC.emptyOutlineView.removeFromSuperview() self.leftSideEmptyVC.deleteOutlineBtn.isEnabled = true } else { // 没有数据 let view = self.tocOutlineView.enclosingScrollView! let emptyVcSize = self.leftSideEmptyVC.emptyOutlineView.frame.size // self.leftSideEmptyVC.emptyOutlineView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height) self.leftSideEmptyVC.emptyOutlineView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin] self.tocOutlineView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.emptyOutlineView) self.leftSideEmptyVC.deleteOutlineBtn.isEnabled = false return 0 } } // 搜索按钮 if outline.numberOfChildren > 0 { self.outlineSearchButton.isEnabled = true } else { self.outlineSearchButton.isEnabled = false } if (self.isSearchOutlineMode) { var num = 0 for i in 0 ..< outline.numberOfChildren { if let child = outline.child(at: i) { if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: child) { num += 1 } } } return num } else { let array = self.listView.document.bookmarks() ?? [CPDFBookmark]() var bookmarkNum = 0 if array.isEmpty == false { bookmarkNum = 1 } return Int(outline.numberOfChildren) + bookmarkNum } } else { // 第二层 + if self.isSearchOutlineMode { if let data = item as? String, data == "Bookmarks" { // 书签group return 0 } else if item is CPDFOutline { // 大纲 let child = item as! CPDFOutline if child.numberOfChildren == 0 { return 0 } var num = 0 for i in 0 ..< child.numberOfChildren { if let _child = child.child(at: i) { if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: _child) { num += 1 } } } return num } else if item is CPDFBookmark { // 书签 return 0 } } else { if let data = item as? String, data == "Bookmarks" { // 书签group return (self.listView.document?.bookmarks().count) ?? 0 } else if item is CPDFOutline { // 大纲 return Int((item as? CPDFOutline)?.numberOfChildren ?? 0) } else if item is CPDFBookmark { // 书签 return 0 } } } } else if outlineView.isEqual(to: self.noteOutlineView) { var count = 0 for section in self._annotations { if section.annotations?.count != 0 { count += section.annotations!.count } } // if (item == nil){ // NSInteger count = [[rightSideController.noteArrayController arrangedObjects] count]; if (count < 1) { // if (notes.count < 1) { self.noteSearchButton.isEnabled = false self.noteFilterButton.isEnabled = false // } self.noteOutlineView.usesAlternatingRowBackgroundColors = false let view = self.noteOutlineView.enclosingScrollView! var emptyVcSize = self.leftSideEmptyVC.emptyAnnotationView.frame.size self.leftSideEmptyVC.emptyAnnotationView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height) self.leftSideEmptyVC.emptyAnnotationView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin] self.noteOutlineView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.emptyAnnotationView) self.leftSideEmptyVC.exportAnnotationBtn.isEnabled = false self.leftSideEmptyVC.deleteAnnotationBtn.isEnabled = false // if (self.leftView.segmentedControl.selectedSegment == KMSelectedSegmentType.annotation.rawValue) { self.noteHeaderView.isHidden = true self.toolButtonBoxLayoutConstraint.constant = 40.0 } } else { self.noteSearchButton.isEnabled = true self.noteFilterButton.isEnabled = true self.noteOutlineView.usesAlternatingRowBackgroundColors = false self.leftSideEmptyVC.emptyAnnotationView.removeFromSuperview() self.leftSideEmptyVC.exportAnnotationBtn.isEnabled = true self.leftSideEmptyVC.deleteAnnotationBtn.isEnabled = true // if (self.leftView.segmentedControl.selectedSegment == KMSelectedSegmentType.annotation.rawValue) { self.noteHeaderView.isHidden = false self.toolButtonBoxLayoutConstraint.constant = 64.0 } } return count; // } else { // return [item hasNoteText]; // } } return 0 } func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { if outlineView.isEqual(to: self.tocOutlineView) { let isLocked = self.listView.document?.isLocked ?? true if isLocked { // 文档不存在 或 已加锁 return "" } let array = self.listView.document.bookmarks() ?? [CPDFBookmark]() var bookmarkNum = 0 if array.isEmpty == false { bookmarkNum = 1 } if item == nil { if self.isSearchOutlineMode { guard let outline = self.listView.document.outlineRoot() else { return "" } if outline.numberOfChildren == 0 { return "" } var array: [CPDFOutline] = [] for i in 0 ..< outline.numberOfChildren { if let child = outline.child(at: i) { if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: child) { array.append(child) } } } if index < array.count { return array[index] } return "" } else { if index == 0 && bookmarkNum == 1 { return "Bookmarks" } else { var _index = bookmarkNum == 1 ? index-1 : index let outline = self.listView.document.outlineRoot() var obj = outline?.child(at: UInt(_index)) return obj as Any } } } else { if let data = item as? String, data == "Bookmarks" { return array[index] } else if item is CPDFOutline { return (item as! CPDFOutline).child(at: UInt(index)) } else if item is CPDFBookmark { return "" } } } else if outlineView.isEqual(to: self.noteOutlineView) { // if (item == nil) // { // return [[rightSideController.noteArrayController arrangedObjects] objectAtIndex:anIndex]; // // return [self.notes objectAtIndex:anIndex]; // } // else // return [item noteText]; var tempArray: [KMBOTAAnnotationItem] = [] for secion in self._annotations { if secion.annotations?.count != 0 { for _item in secion.annotations! { tempArray.append(_item) } } } return tempArray[index] as Any } return item } func outlineView(_ outlineView: NSOutlineView, objectValueFor tableColumn: NSTableColumn?, byItem item: Any?) -> Any? { if outlineView.isEqual(to: self.tocOutlineView) { // let tcID = tableColumn?.identifier.rawValue ?? "" // var ol = item as? CPDFOutline // if(tcID == LABEL_COLUMNID) { // if (self.isSearchOutlineMode) { //// NSString *roughString = [[ol label] stringByCollapsingWhitespaceAndNewlinesAndRemovingSurroundingWhitespaceAndNewlines]? : @""; //// NSArray *arr = [self allRangeOfRoughString:roughString searchString:self.leftSideController.outlineSearchField.stringValue]; //// NSMutableAttributedString *attributeString = [[[NSMutableAttributedString alloc] initWithString:roughString] autorelease]; //// for (NSUInteger i = 0; i NSView? { if outlineView.isEqual(to: self.tocOutlineView) { let cell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMTocTableCellView"), owner: self) as! KMTocTableCellView let tcID = tableColumn?.identifier.rawValue var title = "" var pageLabel = "" if let data = item as? String, data == "Bookmarks" { title = NSLocalizedString("Bookmarks", comment: "") } else if item is CPDFOutline { title = (item as! CPDFOutline).label pageLabel = "\(((item as! CPDFOutline).destination?.pageIndex ?? 0) + 1)" } else if item is CPDFBookmark { title = (item as! CPDFBookmark).label pageLabel = "\((item as! CPDFBookmark).pageIndex + 1)" } if tcID == LABEL_COLUMNID { if (self.isSearchOutlineMode) { // NSString *roughString = [[ol label] stringByCollapsingWhitespaceAndNewlinesAndRemovingSurroundingWhitespaceAndNewlines]; let roughString = title // NSArray *arr = [self allRangeOfRoughString:roughString searchString:self.leftSideController.outlineSearchField.stringValue]; // NSMutableAttributedString *attributeString = [[[NSMutableAttributedString alloc] initWithString:roughString] autorelease]; // // for (NSUInteger i = 0; i CGFloat { if outlineView.isEqual(self.noteOutlineView) { if item is KMBOTAAnnotationItem { let model = item as! KMBOTAAnnotationItem if model.foldType == .fold { return model.foldH } return KMBOTAAnnotationTool.fetchCellHeight(annotation: (item as? KMBOTAAnnotationItem)!.annotation!, maxSize: CGSize(width: 260+40 - 16, height: 1000)) } return 30 } else if outlineView.isEqual(self.tocOutlineView) { if item is CPDFOutline { let tempItem = item as! CPDFOutline let string: NSString = tempItem.label as NSString let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineHeightMultiple = 1.32 paragraphStyle.alignment = .left let attributes = [NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.font : NSFont.SFProTextRegularFont(14.0)] let size = string.boundingRect(with: CGSizeMake(outlineView.frame.size.width - 30, 200), options: NSString.DrawingOptions(rawValue: 3), attributes: attributes) return max(40, size.height + 16) } return 40 } return outlineView.rowHeight } func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { if outlineView.isEqual(self.tocOutlineView) { // var _item: CPDFOutline? // if item == nil && self.listView.document.isLocked == false { // _item = self.listView.document.outlineRoot() // } if let data = item as? String, data == "Bookmarks" { return true } else if item is CPDFOutline { return ((item as! CPDFOutline).numberOfChildren ?? 0) != 0 } else if item is CPDFBookmark { return false } if (self.isSearchOutlineMode) { // return [self subOutLineContainString:self.leftSideController.outlineSearchField.stringValue rootOutline:(PDFOutline *)item]; } else { // return ((_item?.numberOfChildren ?? 0) != 0) } } else if outlineView.isEqual(to: self.noteOutlineView) { // return [item hasNoteText]; return false } return false } func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? { if outlineView.isEqual(self.tocOutlineView) { let itemView = KMBotaTableRowView() return itemView } else if outlineView.isEqual(self.noteOutlineView) { let itemView = KMBotaTableRowView() return itemView; } return nil } func outlineViewSelectionDidChange(_ notification: Notification) { if self.tocOutlineView.isEqual(to: notification.object) { // if ([[notification object] isEqual:leftSideController.tocOutlineView] && (mwcFlags.updatingOutlineSelection == 0)){ // mwcFlags.updatingOutlineSelection = 1; self.goToSelectedOutlineItem(nil) // mwcFlags.updatingOutlineSelection = 0; // if ([self interactionMode] == SKPresentationMode && [[NSUserDefaults standardUserDefaults] boolForKey:SKAutoHidePresentationContentsKey]) // [self hideLeftSideWindow]; } } /* #pragma mark NSOutlineView datasource protocol - (void)outlineView:(NSOutlineView *)ov setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item{ if ([ov isEqual:rightSideController.noteOutlineView]) { PDFAnnotation *note = item; if ([note type]) { if ([[tableColumn identifier] isEqualToString:NOTE_COLUMNID]) { if ([(object ?: @"") isEqualToString:([note string] ?: @"")] == NO) [note setString:object]; } else if ([[tableColumn identifier] isEqualToString:AUTHOR_COLUMNID]) { if ([(object ?: @"") isEqualToString:([note userName] ?: @"")] == NO) [note setUserName:object]; } } } } #pragma mark Drag - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard{ if ([outlineView isEqual:leftSideController.tocOutlineView]) { if (leftSideController.tocOutlineView.selectedRowIndexes.count > 1) { return NO; } NSIndexSet *tIndex = [[[NSIndexSet alloc] initWithIndex:leftSideController.tocOutlineView.clickedRow] autorelease]; [leftSideController.tocOutlineView deselectRow:tIndex.firstIndex]; self.dragPDFOutline = items.firstObject; NSIndexSet *set = [NSIndexSet indexSetWithIndex:0]; NSData *zNSIndexSetData = [NSKeyedArchiver archivedDataWithRootObject:set]; [pasteboard declareTypes:[NSArray arrayWithObject:kKMPDFViewOutlineDragDataType] owner:self]; [pasteboard setData:zNSIndexSetData forType:kKMPDFViewOutlineDragDataType]; return YES; } return NO; } - (NSDragOperation)outlineView:(NSOutlineView *)ov validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(NSInteger)anIndex { NSDragOperation dragOp = NSDragOperationNone; if ([ov isEqual:rightSideController.noteOutlineView]) { NSPasteboard *pboard = [info draggingPasteboard]; if ([pboard canReadObjectForClasses:[NSArray arrayWithObject:[NSColor class]] options:[NSDictionary dictionary]] && anIndex == NSOutlineViewDropOnItemIndex && [(PDFAnnotation *)item type] != nil) dragOp = NSDragOperationEvery; } else if ([ov isEqual:leftSideController.tocOutlineView]) { if (anIndex == -1) { dragOp = NSDragOperationNone; } else { dragOp = NSDragOperationMove; } } return dragOp; } - (BOOL)outlineView:(NSOutlineView *)ov acceptDrop:(id )info item:(id)item childIndex:(NSInteger)anIndex { if ([ov isEqual:rightSideController.noteOutlineView]) { NSPasteboard *pboard = [info draggingPasteboard]; if ([pboard canReadObjectForClasses:[NSArray arrayWithObject:[NSColor class]] options:[NSDictionary dictionary]]) { BOOL isShift = ([NSEvent standardModifierFlags] & NSEventModifierFlagShift) != 0; BOOL isAlt = ([NSEvent standardModifierFlags] & NSEventModifierFlagOption) != 0; [item setColor:[NSColor colorFromPasteboard:pboard] alternate:isAlt updateDefaults:isShift]; return YES; } } else if ([ov isEqual:leftSideController.tocOutlineView]) { if (anIndex < 0) { return NO; } PDFOutline *outline = item; //root,drag item to root if (!outline.parent) { //fetch root PDFOutline *root = self.dragPDFOutline; while (root.parent) { root = root.parent; } if ([self.dragPDFOutline.parent isEqual:root]) { if (self.dragPDFOutline.index > (NSUInteger)anIndex) { [self dragPDFOutline:self.dragPDFOutline toIndex:anIndex newParentOutline:root]; } else { [self dragPDFOutline:self.dragPDFOutline toIndex:anIndex - 1 newParentOutline:root]; } } else { [self dragPDFOutline:self.dragPDFOutline toIndex:anIndex newParentOutline:root]; } } else { //在同一个层级内移动 if ([self.dragPDFOutline.parent isEqual:item]) { if (self.dragPDFOutline.index) { if (self.dragPDFOutline.index > (NSUInteger)anIndex) { [self dragPDFOutline:self.dragPDFOutline toIndex:anIndex newParentOutline:outline]; }else{ [self dragPDFOutline:self.dragPDFOutline toIndex:anIndex - 1 newParentOutline:outline]; } } else { return NO; } } else { PDFOutline *tOutlline = outline; BOOL isContains = NO; while (tOutlline) { if ([tOutlline isEqual:self.dragPDFOutline]) { isContains = YES; break; } tOutlline = tOutlline.parent; } if (!isContains) { [self dragPDFOutline:self.dragPDFOutline toIndex:anIndex newParentOutline:outline]; } } } return YES; } return NO; } #pragma mark NSOutlineView delegate protocol - (NSCell *)outlineView:(NSOutlineView *)ov dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item { if ([ov isEqual:rightSideController.noteOutlineView] && tableColumn == nil && [(PDFAnnotation *)item type] == nil) { return [[ov tableColumnWithIdentifier:NOTE_COLUMNID] dataCellForRow:[ov rowForItem:item]]; } return [tableColumn dataCellForRow:[ov rowForItem:item]]; } - (void)outlineView:(NSOutlineView *)ov willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { if ([ov isEqual:leftSideController.tocOutlineView] && [ov selectionHighlightStyle] == NSTableViewSelectionHighlightStyleRegular && [ov isRowSelected:[ov rowForItem:item]]) { [cell setBackgroundStyle:NSBackgroundStyleLowered]; } } - (BOOL)outlineView:(NSOutlineView *)ov shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item{ if ([ov isEqual:rightSideController.noteOutlineView]) { if (tableColumn == nil) { if ([pdfView hideNotes] == NO && [[(SKNoteText *)item note] isNote]) { PDFAnnotation *annotation = [(SKNoteText *)item note]; [pdfView scrollAnnotationToVisible:annotation]; [pdfView setActiveAnnotation:annotation]; [self showNote:annotation]; SKNoteWindowController *noteController = (SKNoteWindowController *)[self windowControllerForNote:annotation]; [[noteController window] makeFirstResponder:[noteController textView]]; [[noteController textView] selectAll:nil]; } return NO; } else if ([[tableColumn identifier] isEqualToString:NOTE_COLUMNID] || [[tableColumn identifier] isEqualToString:AUTHOR_COLUMNID]) { return YES; } } return NO; } - (void)outlineView:(NSOutlineView *)ov didClickTableColumn:(NSTableColumn *)tableColumn { if ([ov isEqual:rightSideController.noteOutlineView]) { NSTableColumn *oldTableColumn = [ov highlightedTableColumn]; NSTableColumn *newTableColumn = ([NSEvent modifierFlags] & NSEventModifierFlagCommand) ? nil : tableColumn; NSMutableArray *sortDescriptors = nil; BOOL ascending = YES; if ([oldTableColumn isEqual:newTableColumn]) { sortDescriptors = [[[rightSideController.noteArrayController sortDescriptors] mutableCopy] autorelease]; [sortDescriptors replaceObjectAtIndex:0 withObject:[[sortDescriptors firstObject] reversedSortDescriptor]]; ascending = [[sortDescriptors firstObject] ascending]; } else { NSString *tcID = [newTableColumn identifier]; NSSortDescriptor *pageIndexSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:SKNPDFAnnotationPageIndexKey ascending:ascending] autorelease]; NSSortDescriptor *boundsSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:SKPDFAnnotationBoundsOrderKey ascending:ascending selector:@selector(compare:)] autorelease]; sortDescriptors = [NSMutableArray arrayWithObjects:pageIndexSortDescriptor, boundsSortDescriptor, nil]; if ([tcID isEqualToString:TYPE_COLUMNID]) { [sortDescriptors insertObject:[[[NSSortDescriptor alloc] initWithKey:SKNPDFAnnotationTypeKey ascending:YES selector:@selector(noteTypeCompare:)] autorelease] atIndex:0]; } else if ([tcID isEqualToString:COLOR_COLUMNID]) { [sortDescriptors insertObject:[[[NSSortDescriptor alloc] initWithKey:SKNPDFAnnotationColorKey ascending:YES selector:@selector(colorCompare:)] autorelease] atIndex:0]; } else if ([tcID isEqualToString:NOTE_COLUMNID]) { [sortDescriptors insertObject:[[[NSSortDescriptor alloc] initWithKey:SKNPDFAnnotationStringKey ascending:YES selector:@selector(localizedCaseInsensitiveNumericCompare:)] autorelease] atIndex:0]; } else if ([tcID isEqualToString:AUTHOR_COLUMNID]) { [sortDescriptors insertObject:[[[NSSortDescriptor alloc] initWithKey:SKNPDFAnnotationUserNameKey ascending:YES selector:@selector(localizedCaseInsensitiveNumericCompare:)] autorelease] atIndex:0]; } else if ([tcID isEqualToString:DATE_COLUMNID]) { [sortDescriptors insertObject:[[[NSSortDescriptor alloc] initWithKey:SKNPDFAnnotationModificationDateKey ascending:YES] autorelease] atIndex:0]; } if (oldTableColumn) [ov setIndicatorImage:nil inTableColumn:oldTableColumn]; [ov setHighlightedTableColumn:newTableColumn]; } [rightSideController.noteArrayController setSortDescriptors:sortDescriptors]; if (newTableColumn) [ov setIndicatorImage:[NSImage imageNamed:ascending ? @"NSAscendingSortIndicator" : @"NSDescendingSortIndicator"] inTableColumn:newTableColumn]; [ov reloadData]; } } - (NSString *)outlineView:(NSOutlineView *)ov toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)tableColumn item:(id)item mouseLocation:(NSPoint)mouseLocation { if ([ov isEqual:rightSideController.noteOutlineView] && (tableColumn == nil || [[tableColumn identifier] isEqualToString:NOTE_COLUMNID])) { return [item string]; } return @""; } - (void)outlineViewItemDidExpand:(NSNotification *)notification{ if ([[notification object] isEqual:leftSideController.tocOutlineView]) { [self updateOutlineSelection]; } } - (void)outlineViewItemDidCollapse:(NSNotification *)notification{ if ([[notification object] isEqual:leftSideController.tocOutlineView]) { [self updateOutlineSelection]; } } - (void)outlineViewColumnDidResize:(NSNotification *)notification{ if (mwcFlags.autoResizeNoteRows && [[notification object] isEqual:rightSideController.noteOutlineView] && [[[[notification userInfo] objectForKey:@"NSTableColumn"] identifier] isEqualToString:NOTE_COLUMNID] && [(SKScrollView *)[[notification object] enclosingScrollView] isResizingSubviews] == NO) { [rowHeights removeAllFloats]; [rightSideController.noteOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [rightSideController.noteOutlineView numberOfRows])]]; } } - (void)updateSelectRowHeight{ CGFloat rowHeight = 0; PDFOutline *outline = [leftSideController.tocOutlineView itemAtRow:leftSideController.tocOutlineView.selectedRow]; if (!outline){ return; } NSMutableAttributedString *attributedString = [[[NSMutableAttributedString alloc]init] autorelease]; NSDictionary *dictAttr1 = @{NSForegroundColorAttributeName:[KMAppearance KMColor_Layout_H0]}; NSAttributedString *attr1 = [[NSAttributedString alloc]initWithString:outline.label attributes:dictAttr1]; [attributedString appendAttributedString:attr1]; NSInteger *row = [leftSideController.tocOutlineView selectedRow]; NSTableCellView *viewS = [leftSideController.tocOutlineView viewAtColumn:0 row:row makeIfNecessary:YES]; NSTableColumn *tableColumn = [leftSideController.tocOutlineView tableColumnWithIdentifier:LABEL_COLUMNID]; // id cell = [tableColumn dataCell]; id cell = [tableColumn dataCellForRow:row]; [cell setObjectValue:attributedString]; CGFloat w = leftSideController.view.frame.size.width - 86;//[tableColumn width] > 260 ? [tableColumn width] : 260; NSInteger num = [self getNum:outline]; CGFloat gap = [leftSideController.tocOutlineView indentationPerLevel]; rowHeight = [cell cellSizeForBounds:NSMakeRect(0.0, 0.0, w - (num > 0?16:0) - gap*num, CGFLOAT_MAX)].height; rowHeight = fmax(rowHeight, [leftSideController.tocOutlineView rowHeight]) + 25; [rowHeights setFloat:rowHeight forKey:outline]; if (@available(macOS 10.13, *)) { } else { rowHeight = 40.0; } CGRect fram = viewS.frame; viewS.frame = CGRectMake(fram.origin.x, fram.origin.y, fram.size.width, rowHeight); [leftSideController.tocOutlineView reloadData]; } - (NSInteger)getNum:(PDFOutline *)ol{ NSInteger num = 0; PDFOutline *outLine = [ol parent]; do { outLine = [outLine parent]; if (outLine){ num ++; } } while (outLine); return num; } - (void)sizeOutlineViewToContents:(NSOutlineView*) outlineView; { NSInteger rowCount = [outlineView numberOfRows]; for (NSInteger i = 0; i < rowCount; i++){ CGFloat rowHeight = 0; PDFOutline *outline = [leftSideController.tocOutlineView itemAtRow:i]; if (!outline){ continue; } NSMutableAttributedString *attributedString = [[[NSMutableAttributedString alloc]init] autorelease]; NSDictionary *dictAttr1 = @{NSForegroundColorAttributeName:[KMAppearance KMColor_Layout_H0]}; NSAttributedString *attr1 = [[NSAttributedString alloc]initWithString:outline.label attributes:dictAttr1]; [attributedString appendAttributedString:attr1]; // NSTableCellView *viewS = [leftSideController.tocOutlineView viewAtColumn:0 row:i makeIfNecessary:YES]; NSTableColumn *tableColumn = [leftSideController.tocOutlineView tableColumnWithIdentifier:LABEL_COLUMNID]; // id cell = [tableColumn dataCell]; id cell = [tableColumn dataCellForRow:i]; [cell setObjectValue:attributedString]; CGFloat w = leftSideController.view.frame.size.width - 86;//[tableColumn width] > 260 ? [tableColumn width] : 260; NSInteger num = [self getNum:outline]; CGFloat gap = [leftSideController.tocOutlineView indentationPerLevel]; rowHeight = [cell cellSizeForBounds:NSMakeRect(0.0, 0.0, w - (num > 0?16:0) - gap*num, CGFLOAT_MAX)].height; rowHeight = fmax(rowHeight, [leftSideController.tocOutlineView rowHeight]) + 25; [rowHeights setFloat:rowHeight forKey:outline]; if (@available(macOS 10.13, *)) { } else { rowHeight = 40.0; } // CGRect fram = viewS.frame; // viewS.frame = CGRectMake(fram.origin.x, fram.origin.y, fram.size.width, rowHeight); } [leftSideController.tocOutlineView reloadData]; } - (NSArray *)noteItems:(NSArray *)items { NSMutableArray *noteItems = [NSMutableArray array]; for (PDFAnnotation *item in items) { if ([item type] == nil) { item = [(SKNoteText *)item note]; } if ([noteItems containsObject:item] == NO) [noteItems addObject:item]; } return noteItems; } - (NSArray *)outlineView:(NSOutlineView *)ov typeSelectHelperSelectionStrings:(SKTypeSelectHelper *)typeSelectHelper { if ([ov isEqual:rightSideController.noteOutlineView]) { NSInteger i, count = [rightSideController.noteOutlineView numberOfRows]; NSMutableArray *texts = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) { id item = [rightSideController.noteOutlineView itemAtRow:i]; NSString *string = [item string]; [texts addObject:string ?: @""]; } return texts; } else if ([ov isEqual:leftSideController.tocOutlineView]) { NSInteger i, count = [leftSideController.tocOutlineView numberOfRows]; NSMutableArray *array = [NSMutableArray arrayWithCapacity:count]; for (i = 0; i < count; i++) [array addObject:[[(PDFOutline *)[leftSideController.tocOutlineView itemAtRow:i] label] lossyStringUsingEncoding:NSASCIIStringEncoding]]; return array; } return nil; } - (void)outlineView:(NSOutlineView *)ov typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper didFailToFindMatchForSearchString:(NSString *)searchString { if ([ov isEqual:rightSideController.noteOutlineView]) { [statusBar setRightStringValue:[NSString stringWithFormat:NSLocalizedString(@"No match: \"%@\"", @"Status message"), searchString]]; } else if ([ov isEqual:leftSideController.tocOutlineView]) { [statusBar setLeftStringValue:[NSString stringWithFormat:NSLocalizedString(@"No match: \"%@\"", @"Status message"), searchString]]; } } - (void)outlineView:(NSOutlineView *)ov typeSelectHelper:(SKTypeSelectHelper *)typeSelectHelper updateSearchString:(NSString *)searchString { if ([typeSelectHelper isEqual:[leftSideController.thumbnailTableView typeSelectHelper]] || [typeSelectHelper isEqual:[pdfView typeSelectHelper]]) { if (searchString) [statusBar setLeftStringValue:[NSString stringWithFormat:NSLocalizedString(@"Go to page: %@", @"Status message"), searchString]]; else [self updateLeftStatus]; } else if ([typeSelectHelper isEqual:[rightSideController.noteOutlineView typeSelectHelper]]) { if (searchString) [statusBar setRightStringValue:[NSString stringWithFormat:NSLocalizedString(@"Finding note: \"%@\"", @"Status message"), searchString]]; else [self updateRightStatus]; } else if ([typeSelectHelper isEqual:[leftSideController.tocOutlineView typeSelectHelper]]) { if (searchString) [statusBar setLeftStringValue:[NSString stringWithFormat:NSLocalizedString(@"Finding: \"%@\"", @"Status message"), searchString]]; else [self updateLeftStatus]; } } */ } // MARK: - KMCustomOutlineViewDelegate, KMCustomOutlineViewDataSource extension KMLeftSideViewController: KMCustomOutlineViewDelegate, KMCustomOutlineViewDataSource { func outlineView(_ anOutlineView: NSOutlineView, canDeleteItems items: [Any]) -> Bool { if anOutlineView.isEqual(to: self.noteOutlineView) { return self.listView.hideNotes == false && items.count > 0 } else if anOutlineView.isEqual(to: self.tocOutlineView) { return items.count > 0 } return false } func outlineView(_ anOutlineView: NSOutlineView, deleteItems items: [Any]) { if anOutlineView.isEqual(to: self.noteOutlineView) { if (items.isEmpty) { return } // for (PDFAnnotation *item in [self noteItems:items]) // [pdfView removeAnnotation:item]; // [[[self document] undoManager] setActionName:NSLocalizedString(@"Remove Note", @"Undo action name")]; } else if anOutlineView.isEqual(to: self.tocOutlineView) { // [self outlineContextMenuItemClicked_RemoveEntry:nil]; } } func outlineView(_ anOutlineView: NSOutlineView, canCopyItems items: [Any]) -> Bool { if anOutlineView.isEqual(to: self.noteOutlineView) { if (items.count == 1) { // PDFAnnotation *annotation = [[self noteItems:items] lastObject]; // if ([annotation isKindOfClass:[PDFAnnotationStamp class]] || // [annotation isKindOfClass:[PDFAnnotationLink class]]) { // return NO; // } } return items.count > 0 } return false } func outlineView(_ anOutlineView: NSOutlineView, copyItems items: [Any]) { if anOutlineView.isEqual(to: self.noteOutlineView) && items.isEmpty == false { let pboard = NSPasteboard.general var copiedItems: [Any] = [] var attrString = NSMutableAttributedString() var isAttributed = false var item: AnyObject? // for (item in [self noteItems:items]) { // if ([item isMovable]) // [copiedItems addObject:item]; // } // for (item in items) { // if ([attrString length]) // [attrString replaceCharactersInRange:NSMakeRange([attrString length], 0) withString:@"\n\n"]; // if ([(PDFAnnotation *)item type] == nil && [[(SKNoteText *)item note] isNote]) { // [attrString appendAttributedString:[(SKNoteText *)item text]]; // isAttributed = YES; // } else { // [attrString replaceCharactersInRange:NSMakeRange([attrString length], 0) withString:[item string] ?: @""]; // } // } // // [pboard clearContents]; // if (isAttributed) // [pboard writeObjects:[NSArray arrayWithObjects:attrString, nil]]; // else // [pboard writeObjects:[NSArray arrayWithObjects:[attrString string], nil]]; // if ([copiedItems count] > 0) // [pboard writeObjects:copiedItems]; } } } // MARK: - KMTocOutlineViewDelegate extension KMLeftSideViewController: KMTocOutlineViewDelegate { // func outlineView(_ anOutlineView: NSOutlineView, highlightLevelForRow row: Int) -> Int { // if ([ov isEqual:leftSideController.tocOutlineView]) { // NSInteger numRows = [ov numberOfRows]; // NSUInteger firstPage = [[[ov itemAtRow:row] page] pageIndex]; // NSUInteger lastPage = row + 1 < numRows ? [[[ov itemAtRow:row + 1] page] pageIndex] : [[self pdfDocument] pageCount]; // NSRange range = NSMakeRange(firstPage, MAX(1LU, lastPage - firstPage)); // NSUInteger i, iMax = [lastViewedPages count]; // for (i = 0; i < iMax; i++) { // if (NSLocationInRange((NSUInteger)[lastViewedPages pointerAtIndex:i], range)) // return i; // } // } // return NSNotFound; // } func outlineView(_ anOutlineView: NSOutlineView, imageContextForItem item: Any?) -> AnyObject? { if anOutlineView.isEqual(to: self.tocOutlineView) { if item == nil { return true as AnyObject } if item is CPDFOutline { return (item as! CPDFOutline).destination } } return nil } } extension KMLeftSideViewController: KMNoteOutlineViewDelegate { func outlineView(_ anOutlineView: NSOutlineView, canResizeRowByItem item: AnyObject?) -> Bool? { if anOutlineView.isEqual(to: self.noteOutlineView) { return true } return false } func outlineView(_ anOutlineView: NSOutlineView, setHeight newHeight: CGFloat, ofRowByItem item: AnyObject?) { // [rowHeights setFloat:newHeight forKey:item]; } func outlineView(_ anOutlineView: NSOutlineView, didChangeHiddenOfTableColumn aTableColumn: NSTableColumn) { // if (mwcFlags.autoResizeNoteRows && // [ov isEqual:rightSideController.noteOutlineView] && // [[tableColumn identifier] isEqualToString:NOTE_COLUMNID]) { // [rowHeights removeAllFloats]; // [rightSideController.noteOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [rightSideController.noteOutlineView numberOfRows])]]; // } } func outlineViewCommandKeyPressedDuringNavigation(_ anOutlineView: NSOutlineView) { // PDFAnnotation *annotation = [[self selectedNotes] lastObject]; // if (annotation) { // [pdfView scrollAnnotationToVisible:annotation]; // [pdfView setActiveAnnotation:annotation]; // } } } extension KMLeftSideViewController: NSSearchFieldDelegate { func controlTextDidChange(_ obj: Notification) { if self.outlineSearchField.isEqual(to: obj.object) { if (self.outlineSearchField.stringValue.isEmpty == false) { self.isSearchOutlineMode = true self.tocOutlineView.reloadData() self.tocOutlineView.expandItem(nil, expandChildren: true) self.tocType = .unfold } else { self.isSearchOutlineMode = false self.showSearchOutlineBlankState(false) self.tocOutlineView.reloadData() } // self.leftSideEmptyVC.addOutlineBtn.enabled = !self.isSearchOutlineMode; self.outlineAddButton.isEnabled = !self.isSearchOutlineMode } // else if ([obj.object isEqual:self.leftSideController.snapshotSearchField]) { // NSString *searchString = [self.leftSideController.snapshotSearchField stringValue]; // NSPredicate *filterPredicate = nil; // if ([searchString length] > 0) { // NSExpression *lhs = [NSExpression expressionForConstantValue:searchString]; // NSExpression *rhs = [NSExpression expressionForKeyPath:@"string"]; // NSUInteger options = NSDiacriticInsensitivePredicateOption; // if (mwcFlags.caseInsensitiveNoteSearch) // options |= NSCaseInsensitivePredicateOption; // filterPredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:rhs modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:options]; // } // [rightSideController.snapshotArrayController setFilterPredicate:filterPredicate]; // // NSArray * snapshots = [rightSideController.snapshotArrayController arrangedObjects]; // if (snapshots.count > 0) { // [self.leftSideEmptyVC.outlineSearchView removeFromSuperview]; // } else { // NSView *view = rightSideController.snapshotTableView.enclosingScrollView; // CGSize emptyVcSize = self.leftSideEmptyVC.outlineSearchView.frame.size; // self.leftSideEmptyVC.outlineSearchView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height); // self.leftSideEmptyVC.outlineSearchView.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin| NSViewMaxYMargin | NSViewMinYMargin; // [rightSideController.snapshotTableView.enclosingScrollView.documentView addSubview:self.leftSideEmptyVC.outlineSearchView]; // } // } } } extension KMLeftSideViewController: NSMenuDelegate { func menuNeedsUpdate(_ menu: NSMenu) { if menu.isEqual(to: self.tocOutlineView.menu) { menu.removeAllItems() var item = menu.addItem(withTitle: NSLocalizedString("Add Item", comment: ""), action: #selector(outlineContextMenuItemClicked_AddEntry), target: self, tag: 1) item = menu.addItem(withTitle: NSLocalizedString("Add Sub-Item", comment: ""), action: #selector(outlineContextMenuItemClicked_AddChildEntry), target: self, tag: 2) item = menu.addItem(withTitle: NSLocalizedString("Add To A Higher Level", comment: ""), action: #selector(outlineContextMenuItemClicked_AddAuntEntry), target: self, tag: 3) menu.addItem(.separator()) item = menu.addItem(withTitle: NSLocalizedString("Delete", comment: ""), action: #selector(outlineContextMenuItemClicked_RemoveEntry), target: self, tag: 4) menu.addItem(.separator()) item = menu.addItem(withTitle: NSLocalizedString("Edit", comment: ""), action: #selector(outlineContextMenuItemClicked_Edit), target: self, tag: 5) item = menu.addItem(withTitle: NSLocalizedString("Change Destination", comment: ""), action: #selector(outlineContextMenuItemClicked_SetDestination), target: self, tag: 6) item = menu.addItem(withTitle: NSLocalizedString("Rename", comment: ""), action: #selector(outlineContextMenuItemClicked_Rename), target: self, tag: 7) menu.addItem(.separator()) item = menu.addItem(withTitle: NSLocalizedString("Promote", comment: ""), action: #selector(outlineContextMenuItemClicked_Promote), target: self, tag: 8) item = menu.addItem(withTitle: NSLocalizedString("Demote", comment: ""), action: #selector(outlineContextMenuItemClicked_Demote), target: self, tag: 9) return } var item: NSMenuItem? menu.removeAllItems() if menu.isEqual(to: self.thumbnailTableView.menu) { let row = self.thumbnailTableView.clickedRow if self.listView.document.documentURL == nil || self.thumbnailTableView.selectedRowIndexes.contains(row) == false{ return } if (row != -1 && self.listView.document.isLocked == false) { if(self.thumbnailTableView.selectedRowIndexes.count == self.listView.document.pageCount) { item = menu.addItem(title: KMLocalizedString("Cut", "Menu item title"), action: nil, target: self) } else { item = menu.addItem(title: KMLocalizedString("Cut", "Menu item title"), action: #selector(cutPage), target: self) } item?.representedObject = IndexSet(integer: row) item = menu.addItem(title: KMLocalizedString("Copy", "Menu item title"), action: #selector(copyPage), target: self) item?.representedObject = IndexSet(integer: row) if (self._copysPages.count > 0) { item = menu.addItem(title: KMLocalizedString("Paste", "Menu item title"), action: #selector(pastePage), target: self) }else{ item = menu.addItem(title: KMLocalizedString("Paste", "Menu item title"), action: nil, target: self) } item?.representedObject = IndexSet(integer: row) menu.addItem(.separator()) if(self.thumbnailTableView.selectedRowIndexes.count == self.listView.document.pageCount) { item = menu.addItem(title: KMLocalizedString("Delete", "Menu item title"), action: nil, target: self) } else { item = menu.addItem(title: KMLocalizedString("Delete", "Menu item title"), action: #selector(deletePage), target: self) } item?.representedObject = IndexSet(integer: row) menu.addItem(.separator()) item = menu.addItem(title: KMLocalizedString("Rotate", "Menu item title"), action: #selector(rotatePage), target: self) item?.representedObject = IndexSet(integer: row) item = menu.addItem(title: KMLocalizedString("Insert", "Menu item title"), action: nil, target: self) let subMenu = NSMenu() subMenu.addItem(title: KMLocalizedString("Blank Page", "Menu item title"), action: #selector(quickInsert), target: self) subMenu.addItem(title: KMLocalizedString("Blank Page - Custom...", "Menu item title"), action: #selector(insert), target: self) subMenu.addItem(title: KMLocalizedString("From PDF", "Menu item title"), action: #selector(insertPDF), target: self) item?.submenu = subMenu item?.representedObject = IndexSet(integer: row) item = menu.addItem(title: KMLocalizedString("Extract", "Menu item title"), action: #selector(extractPage), target: self) item?.representedObject = IndexSet(integer: row) item = menu.addItem(title: KMLocalizedString("Page Edit", "Menu item title"), action: #selector(pageEdit), target: self) menu.addItem(.separator()) var displayStr = "" if (self.isDisplayPageSize) { displayStr = KMLocalizedString("Hide Page Size", "Menu item title") } else { displayStr = KMLocalizedString("Display Page Size", "Menu item title") } item = menu.addItem(title: displayStr, action: #selector(displayPageSize), target: self) item?.representedObject = IndexSet(integer: row) item = menu.addItem(title: KMLocalizedString("Share", "Menu item title"), action: nil, target: self) // NSString * tName = [self fileNameWithSelectedPages:leftSideController.thumbnailTableView.selectedRowIndexes]; // if (tName.length > 50) { // tName = [tName substringWithRange:NSMakeRange(0, 50)]; // } var tName = self.listView.document.documentURL.lastPathComponent item?.submenu = NSSharingServicePicker.menu(forSharingItems: [self.listView.document.documentURL], subjectContext: tName, withTarget: self, selector: #selector(sharePage), serviceDelegate: nil) } } else if menu.isEqual(to: self.findTableView.menu) { var rowIndexes = self.findTableView.selectedRowIndexes var row = self.findTableView.clickedRow if (row != -1) { if rowIndexes.contains(row) == false { rowIndexes = IndexSet(integer: row) } // NSArray *selections = [[leftSideController.findArrayController arrangedObjects] objectsAtIndexes:rowIndexes]; // if ([pdfView hideNotes] == NO && [[self pdfDocument] allowsNotes]) { item = menu.addItem(withTitle: KMLocalizedString("Add New Circle", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 0) //// [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Rectangle", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 1) //// [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Highlight", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 2) //// [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Underline", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 3) //// [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Strikethrough", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 4) // [item setRepresentedObject:selections]; // } } } else if menu.isEqual(to: self.groupedFindTableView.menu) { var rowIndexes = self.groupedFindTableView.selectedRowIndexes var row = self.groupedFindTableView.clickedRow if (row != -1) { if rowIndexes.contains(row) == false { rowIndexes = IndexSet(integer: row) } // NSArray *selections = [[[leftSideController.groupedFindArrayController arrangedObjects] objectsAtIndexes:rowIndexes] valueForKeyPath:@"@unionOfArrays.matches"]; item = menu.addItem(title: KMLocalizedString("Select", "Menu item title"), action: #selector(selectSelections), target: self) // [item setRepresentedObject:selections]; menu.addItem(.separator()) // if ([pdfView hideNotes] == NO && [[self pdfDocument] allowsNotes]) { item = menu.addItem(withTitle: KMLocalizedString("Add New Circle", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 0) // [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Rectangle", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 1) // [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Highlight", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 2) // [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Underline", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 3) // [item setRepresentedObject:selections]; item = menu.addItem(withTitle: KMLocalizedString("Add New Strikethrough", "Menu item title"), action: #selector(addAnnotationsForSelections), target: self, tag: 4) // [item setRepresentedObject:selections]; // } } } // else if ([menu isEqual:[rightSideController.snapshotTableView menu]]) { // NSInteger row = [rightSideController.snapshotTableView clickedRow]; // if (row != -1) { // SKSnapshotWindowController *controller = [[rightSideController.snapshotArrayController arrangedObjects] objectAtIndex:row]; // // if ([[controller window] isVisible]) { // item = [menu addItemWithTitle:NSLocalizedString(@"Hide", @"Menu item title") action:@selector(hideSnapshot:) target:self]; // [item setRepresentedObject:controller]; // } else { // item = [menu addItemWithTitle:NSLocalizedString(@"Show", @"Menu item title") action:@selector(showSnapshot:) target:self]; // [item setRepresentedObject:controller]; // } // [menu addItem:[NSMenuItem separatorItem]]; // // item = [menu addItemWithTitle:NSLocalizedString(@"Export", @"Menu item title") action:nil target:self]; // NSMenu *subMenu = [NSMenu menu]; // // NSMenuItem *t = [subMenu addItemWithTitle:NSLocalizedString(@"PNG", @"Menu item title") action:@selector(menuItemClick_ExportPNG:) target:self]; // [t setRepresentedObject:controller]; // // t = [subMenu addItemWithTitle:NSLocalizedString(@"JPG", @"Menu item title") action:@selector(menuItemClick_ExportJPG:) target:self]; // [t setRepresentedObject:controller]; // // t = [subMenu addItemWithTitle:NSLocalizedString(@"PDF", @"Menu item title") action:@selector(menuItemClick_ExportPDF:) target:self]; // [t setRepresentedObject:controller]; // item.submenu = subMenu; // // item = [menu addItemWithTitle:NSLocalizedString(@"Print", @"Menu item title") action:@selector(menuItemClick_Print:) target:self]; // [item setRepresentedObject:controller]; // [menu addItem:[NSMenuItem separatorItem]]; // // item = [menu addItemWithTitle:NSLocalizedString(@"Copy", @"Menu item title") action:@selector(menuItemClick_Copy:) target:self]; // [item setRepresentedObject:controller]; // [menu addItem:[NSMenuItem separatorItem]]; // // item = [menu addItemWithTitle:NSLocalizedString(@"Delete", @"Menu item title") action:@selector(deleteSnapshot:) target:self]; // [item setRepresentedObject:controller]; // item = [menu addItemWithTitle:NSLocalizedString(@"Delete All Snapshots", @"Menu item title") action:@selector(deleteAllSnapshot:) target:self]; // [item setRepresentedObject:controller]; // } // } else if menu.isEqual(to: self.noteOutlineView.menu) { // NSArray *items; var rowIndexes = self.noteOutlineView.selectedRowIndexes let row = self.noteOutlineView.clickedRow if (row != -1) { if rowIndexes.contains(row) == false { rowIndexes = IndexSet(integer: row) // items = [rightSideController.noteOutlineView itemsAtRowIndexes:rowIndexes]; // PDFAnnotation *foldNote = (PDFAnnotation *)notes[row]; var isFold = true // if ([rightSideController.allFoldNotes containsObject:foldNote]) { // isFold = NO; // } item = menu.addItem(title: KMLocalizedString("Expand", nil), action: #selector(unfoldNoteAction), target: self) if (isFold) { item?.state = .off } else { item?.state = .on } // [item setRepresentedObject:items]; item = menu.addItem(title: KMLocalizedString("Collapse", nil), action: #selector(foldNoteAction), target: self) if (isFold) { item?.state = .on } else { item?.state = .off } // [item setRepresentedObject:items]; //UX改版删除 // if ([self outlineView:rightSideController.noteOutlineView canCopyItems:items]) { // item = [menu addItemWithTitle:NSLocalizedString(@"Copy", @"Menu item title") action:@selector(copyNotes:) target:self]; // [item setRepresentedObject:items]; // } menu.addItem(.separator()) if self.listView.hideNotes == false { // if ([pdfView hideNotes] == NO && [items count] == 1) { // PDFAnnotation *annotation = [[self noteItems:items] lastObject]; // if ([annotation isEditable]) { // if ([(PDFAnnotation *)[items lastObject] type] == nil) { // if ([[(SKNoteText *)[items lastObject] note] isNote]) { // item = [menu addItemWithTitle:[NSLocalizedString(@"Edit", @"Menu item title") stringByAppendingEllipsis] action:@selector(editNoteTextFromTable:) target:self]; // [item setRepresentedObject:annotation]; // } // } else if ([[rightSideController.noteOutlineView tableColumnWithIdentifier:NOTE_COLUMNID] isHidden]) { // item = [menu addItemWithTitle:[NSLocalizedString(@"Edit", @"Menu item title") stringByAppendingEllipsis] action:@selector(editThisAnnotation:) target:pdfView]; // [item setRepresentedObject:annotation]; // } else { // item = [menu addItemWithTitle:NSLocalizedString(@"Edit", @"Menu item title") action:@selector(editNoteFromTable:) target:self]; // [item setRepresentedObject:annotation]; // item = [menu addItemWithTitle:[NSLocalizedString(@"Edit", @"Menu item title") stringByAppendingEllipsis] action:@selector(editThisAnnotation:) target:pdfView]; // [item setRepresentedObject:annotation]; // [item setKeyEquivalentModifierMask:NSEventModifierFlagOption]; // [item setAlternate:YES]; // } // } // if ([pdfView hideNotes] == NO && [[self pdfDocument] allowsNotes]) { // if ([pdfView activeAnnotation] == annotation) { // item = [menu addItemWithTitle:NSLocalizedString(@"Deselect", @"Menu item title") action:@selector(deselectNote:) target:self]; // [item setRepresentedObject:annotation]; // } else { // item = [menu addItemWithTitle:NSLocalizedString(@"Select", @"Menu item title") action:@selector(selectNote:) target:self]; // [item setRepresentedObject:annotation]; // } // item = [menu addItemWithTitle:NSLocalizedString(@"Show", @"Menu item title") action:@selector(revealNote:) target:self]; // [item setRepresentedObject:annotation]; // } // } // if ([menu numberOfItems] > 0) // [menu addItem:[NSMenuItem separatorItem]]; // item = [menu addItemWithTitle:[items count] == 1 ? NSLocalizedString(@"Auto Size Row", @"Menu item title") : NSLocalizedString(@"Auto Size Rows", @"Menu item title") action:@selector(autoSizeNoteRows:) target:self]; // [item setRepresentedObject:items]; // item = [menu addItemWithTitle:[items count] == 1 ? NSLocalizedString(@"Undo Auto Size Row", @"Menu item title") : NSLocalizedString(@"Undo Auto Size Rows", @"Menu item title") action:@selector(resetHeightOfNoteRows:) target:self]; // [item setRepresentedObject:items]; // [item setKeyEquivalentModifierMask:NSAlternateKeyMask]; // [item setAlternate:YES]; // [menu addItemWithTitle:NSLocalizedString(@"Auto Size All", @"Menu item title") action:@selector(autoSizeNoteRows:) target:self]; // item = [menu addItemWithTitle:NSLocalizedString(@"Undo Auto Size All", @"Menu item title") action:@selector(resetHeightOfNoteRows:) target:self]; // [item setKeyEquivalentModifierMask:NSAlternateKeyMask]; // [item setAlternate:YES]; // [menu addItemWithTitle:NSLocalizedString(@"Automatically Resize", @"Menu item title") action:@selector(toggleAutoResizeNoteRows:) target:self]; if menu.numberOfItems > 0 { item = menu.addItem(title: NSLocalizedString("Export Annotations…", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) let subMenu = NSMenu() item?.submenu = subMenu item = subMenu.addItem(title: NSLocalizedString("PDF", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) item?.tag = 0 item = subMenu.addItem(title: NSLocalizedString("PDF Bundle", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) item?.tag = 1 item = subMenu.addItem(title: NSLocalizedString("PDF Reader Pro Edition Notes", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) item?.tag = 2 item = subMenu.addItem(title: NSLocalizedString("Notes as Texts", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) item?.tag = 3 item = subMenu.addItem(title: NSLocalizedString("Notes as RTF", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) item?.tag = 4 item = subMenu.addItem(title: NSLocalizedString("Notes as RTFD", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) item?.tag = 5 item = subMenu.addItem(title: NSLocalizedString("Notes as FDF", tableName: "MainMenu", comment: "Menu item title"), action: #selector(exportAnnotationNotes), target: self) item?.tag = 6 menu.addItem(.separator()) // if ([self outlineView:rightSideController.noteOutlineView canDeleteItems:items]) { item = menu.addItem(title: KMLocalizedString("Delete", "Menu item title"), action: #selector(deleteNotes), target: self) // [item setRepresentedObject:items]; // } item = menu.addItem(title: NSLocalizedString("Remove All Annotations", tableName: "MainMenu", comment: "Menu item title"), action: #selector(removeAllAnnotations), target: self) } } } } } // else { // item = [menu addItemWithTitle:NSLocalizedStringFromTable(@"Export Annotations…", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // // NSMenu *subMenu = [NSMenu menu]; // item.submenu = subMenu; // item = [subMenu addItemWithTitle:NSLocalizedStringFromTable(@"PDF", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // item.tag = 0; // item = [subMenu addItemWithTitle:NSLocalizedStringFromTable(@"PDF Bundle", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // item.tag = 1; // item = [subMenu addItemWithTitle:NSLocalizedStringFromTable(@"PDF Reader Pro Edition Notes", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // item.tag = 2; // item = [subMenu addItemWithTitle:NSLocalizedStringFromTable(@"Notes as Text", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // item.tag = 3; // item = [subMenu addItemWithTitle:NSLocalizedStringFromTable(@"Notes as RTF", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // item.tag = 4; // item = [subMenu addItemWithTitle:NSLocalizedStringFromTable(@"Notes as RTFD", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // item.tag = 5; // item = [subMenu addItemWithTitle:NSLocalizedStringFromTable(@"Notes as FDF", @"MainMenu", @"Menu item title") action:@selector(exportAnnotationNotes:) target:self]; // item.tag = 6; // // item = [menu addItemWithTitle:NSLocalizedStringFromTable(@"Remove All Annotations", @"MainMenu", @"Menu item title") action:@selector(removeAllAnnotations:) target:self]; // } // } } } // MARK: - Menu Item Actions extension KMLeftSideViewController { @objc func cutPage(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-cutPage...") // if (![IAPProductsManager defaultManager].isAvailableAllFunction) { // [[KMPurchaseCompareWindowController sharedInstance] showWindow:nil]; // return; // } // [self tableView:leftSideController.thumbnailTableView cutRowsWithIndexes:leftSideController.thumbnailTableView.selectedRowIndexes]; } @objc func copyPage(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-copyPage...") // [self tableView:leftSideController.thumbnailTableView copyRowsWithIndexes:leftSideController.thumbnailTableView.selectedRowIndexes]; } @objc func pastePage(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-pastePage...") // [self tableView:leftSideController.thumbnailTableView pasteFromPasteboard:nil]; } @objc func deletePage(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-deletePage...") // if (![IAPProductsManager defaultManager].isAvailableAllFunction) { // [[KMPurchaseCompareWindowController sharedInstance] showWindow:nil]; // return; // } // [self tableView:leftSideController.thumbnailTableView deleteRowsWithIndexes:leftSideController.thumbnailTableView.selectedRowIndexes]; } @objc func rotatePage(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-rotatePage...") // if (![IAPProductsManager defaultManager].isAvailableAllFunction) { // [[KMPurchaseCompareWindowController sharedInstance] showWindow:nil]; // return; // } // // [self tableView:leftSideController.thumbnailTableView rotateRowsWithIndexes:leftSideController.thumbnailTableView.selectedRowIndexes]; } @objc func quickInsert(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-quickInsert...") } @objc func insert(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-insert...") } @objc func insertPDF(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-insertPDF...") } @objc func extractPage(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-extractPage...") } @objc func pageEdit(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-pageEdit...") } @objc func displayPageSize(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-displayPageSize...") } @objc func sharePage(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-sharePage...") } @objc func unfoldNoteAction(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-unfoldNoteAction...") } @objc func foldNoteAction(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-foldNoteAction...") } @objc func deleteNotes(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-deleteNotes...") } @objc func removeAllAnnotations(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-removeAllAnnotations...") } @objc func addAnnotationsForSelections(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-addAnnotationsForSelections...") } @objc func selectSelections(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-selectSelections...") } @objc func toggleWholeWordSearch(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-toggleWholeWordSearch...") } @objc func toggleCaseInsensitiveSearch(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-toggleCaseInsensitiveSearch...") } @objc func toggleCaseInsensitiveNoteSearch(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-toggleCaseInsensitiveNoteSearch...") } @objc func searchNotes(_ sender: AnyObject?) { if self.findState == .note { // if (mwcFlags.findState == SKFindStateNote) // [self updateNoteFilterPredicate]; } // else // [self updateSnapshotFilterPredicate]; // if ([[sender stringValue] length]) { // NSPasteboard *findPboard = [NSPasteboard pasteboardWithName:NSPasteboardNameFind]; // [findPboard clearContents]; // [findPboard writeObjects:[NSArray arrayWithObjects:[sender stringValue], nil]]; // } } @objc func toggleSelectedSnapshots(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-toggleSelectedSnapshots...") } @objc func toggleOutlineCaseInsensitiveSearch(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-toggleOutlineCaseInsensitiveSearch...") } @objc func outlineContextMenuItemClicked_AddEntry(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_AddEntry...") } @objc func outlineContextMenuItemClicked_AddChildEntry(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_AddChildEntry...") } @objc func outlineContextMenuItemClicked_AddAuntEntry(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_AddAuntEntry...") } @objc func outlineContextMenuItemClicked_RemoveEntry(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_RemoveEntry...") } @objc func outlineContextMenuItemClicked_Edit(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_Edit...") } @objc func outlineContextMenuItemClicked_SetDestination(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_SetDestination...") } @objc func outlineContextMenuItemClicked_Rename(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_Rename...") } @objc func outlineContextMenuItemClicked_Promote(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_Promote...") } @objc func outlineContextMenuItemClicked_Demote(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-outlineContextMenuItemClicked_Demote...") } private func _tableView(_ tv: NSTableView, cutRowsWithIndexes rowIndexes: IndexSet) { // if tv.isEqual(to: self.thumbnailTableView) { // self._copysPages.removeAll() // for i in rowIndexes { // if (idx != NSNotFound) { // let page = self.listView.document.page(at: idx) // self._copysPages.append(page) // } // } // [self tableView:tv deleteRowsWithIndexes:rowIndexes]; // } } } // MARK: - Other extension KMLeftSideViewController { @objc func goToSelectedOutlineItem(_ sender: AnyObject?) { let outlineItem = self.tocOutlineView.item(atRow: self.tocOutlineView.selectedRow) let outline = self.tocOutlineView if let cnt = outline?.selectedRowIndexes.count, cnt == 1 { if outlineItem is CPDFOutline { let outline = (outlineItem as! CPDFOutline) if let des = outline.destination { self.listView.go(to: des) } else if let action = outline.action { self.listView.perform(action) } } else if outlineItem is CPDFBookmark { let bookmark = outlineItem as! CPDFBookmark self.listView.go(toPageIndex: bookmark.pageIndex, animated: true) } } } @objc func goToSelectedFindResults(_ sender: AnyObject?) { KMPrint("KMLeftSideViewController-goToSelectedFindResults...") } }