// // KMLeftSideViewController+Snapshot.swift // PDF Master // // Created by tangchao on 2024/1/12. // import Foundation extension KMLeftSideViewController.Key { static let snapshotSizeScaling = "KMSnapshotSizeScalingKey" } // MARK: - Actions extension KMLeftSideViewController { @objc func menuItemClick_ExportPNG(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } let image = snapshot.thumbnailWithSize(0) NSPanel.savePanel_data_success(self.view.window!, imageData: image?.pngData(), allowedTypes: ["png"]) { url in NSWorkspace.shared.selectFile(url.path, inFileViewerRootedAtPath: "") } } @objc func menuItemClick_ExportJPG(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } let image = snapshot.thumbnailWithSize(0) NSPanel.savePanel_data_success(self.view.window!, imageData: image?.jpgData(), allowedTypes: ["jpg"]) { url in NSWorkspace.shared.selectFile(url.path, inFileViewerRootedAtPath: "") } } @objc func menuItemClick_ExportPDF(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } if let image = snapshot.thumbnailWithSize(0) { let document = CPDFDocument() _ = document?.km_insert(image: image, at: 0) NSPanel.savePanel_pdf_success(self.view.window!, document: document) { url in NSWorkspace.shared.selectFile(url.path, inFileViewerRootedAtPath: "") } } } @objc func menuItemClick_Print(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } if let image = snapshot.thumbnailWithSize(0) { self.delegate?.controller?(controller: self, itemClick: nil, itemKey: .print, params: image) } } @objc func menuItemClick_SelectAll(_ sender: AnyObject?) { let selected = self.snapshotListIsAllSelected() for model in self.snapshots { model.isSelected = !selected } Task { @MainActor in self.snapshotTableView.reloadData() } } @objc func deleteAllSnapshot(_ sender: AnyObject?) { for model in self.snapshots { model.windowC?.close() } } @objc func hideSnapshot(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } if let data = snapshot.window?.isVisible, data { snapshot.miniaturize() } } @objc func showSnapshot(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } if let data = snapshot.window?.isVisible, data { snapshot.window?.orderFront(nil) } else { snapshot.deminiaturize() } } @objc func deleteSnapshot(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } snapshot.close() } @objc func menuItemClick_Copy(_ sender: AnyObject?) { guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else { return } let image = snapshot.thumbnailWithSize(0) if let tiffData = image?.tiffRepresentation { let pasteboardItem = NSPasteboardItem() pasteboardItem.setData(tiffData, forType: .tiff) let pboard = NSPasteboard.general pboard.clearContents() pboard.writeObjects([pasteboardItem]) } } func snapshot_initSubViews() { self.snapshotNormalZoomInButton.target = self self.snapshotNormalZoomInButton.tag = 2 self.snapshotNormalZoomInButton.action = #selector(thumbnailSizeScaling) self.snapshotNormalZoomOutButton.target = self self.snapshotNormalZoomOutButton.tag = 3 self.snapshotNormalZoomOutButton.action = #selector(thumbnailSizeScaling) self.snapshotNormalMoreButton.target = self self.snapshotNormalMoreButton.tag = 300 self.snapshotNormalMoreButton.action = #selector(leftSideViewMoreButtonAction) self.snapshotSearchZoomInButton.target = self self.snapshotSearchZoomInButton.tag = 2 self.snapshotSearchZoomInButton.action = #selector(thumbnailSizeScaling) self.snapshotSearchZoomOutButton.target = self self.snapshotSearchZoomOutButton.tag = 3 self.snapshotSearchZoomOutButton.action = #selector(thumbnailSizeScaling) self.snapshotDoneButton.target = self self.snapshotDoneButton.tag = 312 self.snapshotDoneButton.action = #selector(leftSideViewDoneButtonAction) self.snapshotTableView.delegate = self self.snapshotTableView.dataSource = self self.snapshotTableView.menu = NSMenu() self.snapshotTableView.menu?.delegate = self self.snapshotTableView.doubleAction = #selector(toggleSelectedSnapshots) self.snapshotTableView.target = self self.snapshotTableView.botaDelegate = self self.snapshotTableView.setDraggingSourceOperationMask(.every, forLocal: false) self.snapshotSearchField.changeCallBack = { [weak self] changeContent in var editContent = "" if changeContent != nil { editContent = changeContent! } self?.searchFieldChangeAction(editContent) } } func snapshot_initDefalutValue() { self.snapshotNormalView.wantsLayer = true self.snapshotNormalView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor self.snapshotLabel.stringValue = KMLocalizedString("Snapshots", nil) self.snapshotLabel.textColor = KMAppearance.Layout.h0Color() self.snapshotNormalSearchButton.toolTip = KMLocalizedString("Search", nil) self.snapshotSearchField.backgroundColor = KMAppearance.Layout.l_1Color() self.snapshotSearchField.wantsLayer = true self.snapshotSearchField.layer?.backgroundColor = KMAppearance.Layout.l_1Color().cgColor self.snapshotSearchField.layer?.borderWidth = 1.0 self.snapshotSearchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor self.snapshotDoneButton.toolTip = KMLocalizedString("Done", nil) self.snapshotDoneButton.wantsLayer = true self.snapshotDoneButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor self.snapshotDoneButton.layer?.cornerRadius = 4.0 self.snapshotDoneButton.title = KMLocalizedString("Done", nil) self.snapshotDoneButton.setTitleColor(KMAppearance.Layout.w0Color()) self.snapshotDoneButton.isHidden = true self.snapshotSearchField.isHidden = true self.snapshotSearchZoomOutButton.isHidden = true self.snapshotSearchZoomInButton.isHidden = true self.snapshotNormalZoomInButton.toolTip = KMLocalizedString("Zoom In", nil) self.snapshotSearchZoomInButton.toolTip = KMLocalizedString("Zoom In", nil) self.snapshotNormalZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil) self.snapshotSearchZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil) self.snapshotTableView.backgroundColor = KMAppearance.Layout.l0Color() // self.snapshotTableView.backgroundColor = .clear } func updataLeftSideSnapView() { if (snapshots.count < 1) { self.snapshotNormalSearchButton.isEnabled = false self.snapshotNormalZoomOutButton.isEnabled = false 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 viewSize = view?.frame.size ?? .zero let emptyVcSize = self.leftSideEmptyVC.emptySnapView.frame.size self.leftSideEmptyVC.emptySnapView.frame = NSMakeRect((viewSize.width-emptyVcSize.width)/2.0,(viewSize.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 self.snapshotNormalZoomOutButton.isEnabled = true 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 } } @IBAction func snapshotNormalSearchButtonAction(_ sender: NSButton) { self.snapshotSearchField.isHidden = false 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() } } extension KMLeftSideViewController { public func refreshUIOfSnapshotIfNeed(preference: Bool = false) { if self.type.methodType != .snapshot { return } if preference { self.reloadSnapshotSize() } Task { @MainActor in self.snapshotTableView.reloadData() } } public func reloadSnapshotDataIfNeed() { if self.type.methodType != .Thumbnail { return } Task { @MainActor in self.snapshotTableView.reloadData() } } public func reloadSnapshotSize() { let defaultSize = roundf(KMPreference.shared.thumbSnapshotSize) var thumbnailSize = Self.kTinySize if defaultSize < Self.kTinySize + Self.kFudgeSize { } else { if defaultSize < Self.kSmallSize + Self.kFudgeSize { thumbnailSize = Self.kSmallSize } else { if defaultSize < Self.kLargeSize + Self.kFudgeSize { thumbnailSize = Self.kLargeSize } else { thumbnailSize = Self.kHugeSize } } } if (abs(thumbnailSize - Float(self.snapshotCacheSize)) > Self.kFudgeSize) { self.snapshotCacheSize = thumbnailSize.cgFloat } Task { @MainActor in self.snapshotTableView.reloadData() } } func updateSnapshotsIfNeed(for page: CPDFPage?) { if self.type.methodType != .Thumbnail { return } if page != nil { for model in self.snapshots { if let wc = model.windowC, wc.isPageVisible(page) { self.snapshotNeedsUpdate(wc) wc.redisplay() } } } else { for model in self.snapshots { model.windowC?.redisplay() } self.allSnapshotsNeedUpdate() } } func snapshotNeedsUpdate(_ dirtySnapshot: KMSnapshotWindowController) { if self.dirtySnapshots.contains(dirtySnapshot) == false { self.dirtySnapshots.append(dirtySnapshot) self.updateSnapshotsIfNeeded() } } func updateSnapshotsIfNeeded() { // if ([rightSideController.snapshotTableView window] != nil && [dirtySnapshots count] > 0 && snapshotTimer == nil) // snapshotTimer = [[NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(updateSnapshot:) userInfo:NULL repeats:YES] retain]; } func allSnapshotsNeedUpdate() { self.dirtySnapshots.removeAll() for model in self.snapshots { if let winC = model.windowC { self.dirtySnapshots.append(winC) } } self.updateSnapshotsIfNeeded() } } extension KMLeftSideViewController: KMSnapshotWindowControllerDelegate { func snapshotControllerWillClose(_ controller: KMSnapshotWindowController) { var flag: KMSnapshotModel? for model in self.snapshots { if controller.isEqual(model.windowC) { flag = model } } if flag != nil { self.snapshots.removeObject(flag!) Task { @MainActor in self.snapshotTableView.reloadData() self.updataLeftSideSnapView() } } } func snapshotControllerDidFinishSetup(_ controller: KMSnapshotWindowController) { let image = controller.thumbnailWithSize(self.snapshotCacheSize) controller.thumbnail = image let model = KMSnapshotModel() model.windowC = controller self.snapshots.append(model) Task { @MainActor in self.snapshotTableView.ks_reloadData() } } func snapshotController(_ controller: KMSnapshotWindowController, miniaturizedRect isMiniaturize: Bool) -> NSRect { var row = NSNotFound for (i,sp) in self.snapshots.enumerated() { if controller.isEqual(sp.windowC) { row = i } } var rect: NSRect = .zero if (row != NSNotFound) { rect = self.snapshotTableView.frameOfCell(atColumn: 0, row: row) } else { rect.origin = KMBottomLeftPoint(self.snapshotTableView.visibleRect) rect.size.width = 1.0 rect.size.height = 1.0 } rect = self.snapshotTableView.convertRectToScreen(rect) return rect } }