// // KMEditImagePropertyViewController.swift // PDF Reader Pro // // Created by lxy on 2022/12/28. // import Cocoa public enum KMOperationState { case none case began case changed case ended } enum KMEditImagePropertyViewControllerChangeType { case rotate case flip case add case move } protocol KMEditImagePropertyViewControllerDelegate: NSObject { func editImagePropertyViewControllerDidChanged(controller: KMEditImagePropertyViewController, type: KMEditImagePropertyViewControllerChangeType) } class KMEditImagePropertyViewController: NSViewController { @IBOutlet weak var backgroundView: NSView! @IBOutlet weak var titleLabel: NSTextField! @IBOutlet weak var editImageView: NSImageView! @IBOutlet weak var headerBox: NSBox! @IBOutlet weak var headerBoxHeight: NSLayoutConstraint! @IBOutlet weak var headerBoxMaginWidthConstraint: NSLayoutConstraint! @IBOutlet weak var opacityTitleLabel: NSTextField! @IBOutlet weak var opacitySlider: NSSlider! @IBOutlet weak var opacityBox: NSBox! @IBOutlet weak var opacityBoxBottomMaginConstraint: NSLayoutConstraint! @IBOutlet weak var opacityBoxTopConstraint: NSLayoutConstraint! @IBOutlet weak var cropBox: NSBox! @IBOutlet weak var confirmBox: NSBox! @IBOutlet weak var cancelBox: NSBox! @IBOutlet weak var replaceBox: NSBox! @IBOutlet weak var exportBox: NSBox! @IBOutlet weak var imageBox: NSBox! @IBOutlet weak var imageBoxHeight: NSLayoutConstraint! @IBOutlet weak var opacityBoxHeight: NSLayoutConstraint! @IBOutlet weak var buttonBoxHeight: NSLayoutConstraint! @IBOutlet weak var buttonBox: NSBox! @IBOutlet weak var rotateLeftBox: NSBox! @IBOutlet weak var rotateRightBox: NSBox! @IBOutlet weak var flipHorizontalBox: NSBox! @IBOutlet weak var flipVerticalBox: NSBox! @IBOutlet weak var alignmentView: KMEditPropertyAlignmentView! @IBOutlet weak var alignmentViewTopConstraint: NSLayoutConstraint! //NO Image @IBOutlet weak var noImageView: NSImageView! @IBOutlet weak var noTitleLabel: NSTextField! @IBOutlet weak var noSubtitleLabel: NSTextField! @IBOutlet weak var noBackgroundView: NSView! var rotateLeftVC: KMDesignPropertySelector? var rotateRightVC: KMDesignPropertySelector? var flipHorizontalVC: KMDesignPropertySelector? var flipVerticalVC: KMDesignPropertySelector? var opacityVC: KMDesignSelect? var cropVC: KMDesignButton? var confirmVC: KMDesignButton? var cancelVC: KMDesignButton? var replaceVC: KMDesignButton? var exportVC: KMDesignButton? var imagesAreas : [CPDFEditImageArea] = [] var listView : CPDFListView! var editingAreas: [Any] { get { return self.listView.editingAreas() ?? [] } } weak var delegate: KMEditImagePropertyViewControllerDelegate? func addNotification() { NotificationCenter.default.addObserver(self, selector: #selector(changeEffectiveAppearance), name: NSNotification.Name(rawValue: "kEffectiveAppearance"), object: nil) } func removeNotification() { NotificationCenter.default.removeObserver(self) DistributedNotificationCenter.default().removeObserver(self) } @objc func changeEffectiveAppearance() { print("changeEffectiveAppearance") let isDarkModel = NSView.isDarkModel() if isDarkModel { self.view.appearance = NSAppearance(named: .darkAqua) } else { self.view.appearance = NSAppearance(named: .aqua) } self.updateUI() } func updateUI() { let isDarkModel = NSView.isDarkModel() if isDarkModel { self.backgroundView.backgroundColor(NSColor.km_init(hex: "#252526")) self.noBackgroundView.backgroundColor(NSColor.km_init(hex: "#252526")) } else { self.backgroundView.backgroundColor(NSColor.km_init(hex: "#FAFAFA")) self.noBackgroundView.backgroundColor(NSColor.km_init(hex: "#F7F8FA")) } } deinit { self.removeNotification() } override func viewDidLoad() { super.viewDidLoad() self.setup() self.initData() self.updateLanguage() self.updateButtonState(hidden: true) self.reloadData() self.addNotification() self.updateUI() } func initData() { self.updateButtonState(hidden: true) } func setup() { self.titleLabel.font = NSFont.SFProTextSemiboldFont(14.0) // self.titleLabel.textColor = NSColor.km_init(hex: "#252629") self.titleLabel.textColor = KMAppearance.Layout.h0Color() self.opacityTitleLabel.font = NSFont.SFProTextSemiboldFont(12.0) // self.opacityTitleLabel.textColor = NSColor.km_init(hex: "#616469") self.opacityTitleLabel.textColor = KMAppearance.Layout.h0Color() self.imageBox.borderWidth = 1 // self.imageBox.borderColor = NSColor.km_init(hex: "#DFE1E5") self.imageBox.cornerRadius = 4 // self.imageBox.fillColor = NSColor.km_init(hex: "#FFFFFF") self.imageBox.borderColor = KMAppearance.Interactive.s0Color() self.imageBox.fillColor = KMAppearance.Layout.l1Color() self.imageBox.backgroundColor(KMAppearance.Layout.l1Color()) self.alignmentView.didChange = {[unowned self] view, areasArray, boundsArray in self.changeAreasAlign(areas: areasArray, newBounds: boundsArray) } opacityVC = KMDesignSelect.init(withType: .PopButton) opacityBox.contentView = opacityVC?.view opacityBox.fillColor = KMAppearance.Layout.bgDrakColor() opacityVC?.addItems(withObjectValues: ["25%","50%","75%","100%"]) opacityVC?.selectItem(at: 0) opacityVC?.delete = self opacityVC?.borderColor = KMAppearance.Interactive.s0Color() opacityVC?.borderColor_disabled = KMAppearance.Interactive.s0Color() opacityVC?.background = KMAppearance.Layout.l1Color() opacityVC?.background_hov = KMAppearance.Layout.l1Color() opacityVC?.background_focus = KMAppearance.Layout.l1Color() opacityVC?.background_disabled = KMAppearance.Layout.l1Color() opacityVC?.textColor = KMAppearance.Layout.h1Color() opacityVC?.textColor_hov = KMAppearance.Layout.h1Color() opacityVC?.textColor_focus = KMAppearance.Layout.h1Color() opacityVC?.popViewControllerBackground = KMAppearance.Layout.bgColor() opacityVC?.popViewControllerTextColor = KMAppearance.Layout.h0Color() opacityVC?.popViewControllerEnterFillColor = KMAppearance.Interactive.s0Color() opacityVC?.updateUI() //alignment rotateLeftVC = KMDesignPropertySelector.init(withType: .Icon_Btn) rotateLeftBox.contentView = rotateLeftVC?.view rotateLeftBox.fillColor = NSColor.clear rotateLeftVC?.target = self rotateLeftVC?.action = #selector(leftRotationImageAction) rotateLeftVC?.image = NSImage(named: "KMImageNameEditPDFRotationLeft")! rotateLeftVC?._image_disabled = NSImage(named: "KMImageNameEditPDFRotationLeft")! rotateLeftVC?.background_hov = KMAppearance.buttonHoverColor() rotateLeftVC?.updateUI() rotateRightVC = KMDesignPropertySelector.init(withType: .Icon_Btn) rotateRightBox.contentView = rotateRightVC?.view rotateRightBox.fillColor = NSColor.clear rotateRightVC?.target = self rotateRightVC?.action = #selector(rightRotationImageAction) rotateRightVC?.image = NSImage(named: "KMImageNameEditPDFRotationRight")! rotateRightVC?.background_hov = KMAppearance.buttonHoverColor() rotateRightVC?.updateUI() flipHorizontalVC = KMDesignPropertySelector.init(withType: .Icon_Btn) flipHorizontalBox.contentView = flipHorizontalVC?.view flipHorizontalBox.fillColor = NSColor.clear flipHorizontalVC?.target = self flipHorizontalVC?.action = #selector(flipHorizontalImageAction) flipHorizontalVC?.image = NSImage(named: "KMImageNameEditPDFFlipHorizontal")! flipHorizontalVC?.background_hov = KMAppearance.buttonHoverColor() flipHorizontalVC?.updateUI() flipVerticalVC = KMDesignPropertySelector.init(withType: .Icon_Btn) flipVerticalBox.contentView = flipVerticalVC?.view flipVerticalBox.fillColor = NSColor.clear flipVerticalVC?.target = self flipVerticalVC?.action = #selector(flipVerticalImageAction) flipVerticalVC?.image = NSImage(named: "KMImageNameEditPDFFlipVertical")! flipVerticalVC?.background_hov = KMAppearance.buttonHoverColor() flipVerticalVC?.updateUI() // 设置默认状态下的滑块图像 let customCell = CustomSliderCell() // 设置滑块图像 customCell.knobImage = NSImage(named: "KMImageNameEditPDFSlider") // 应用自定义的NSSliderCell到NSSlider opacitySlider.cell = customCell // 添加滑动事件处理程序 opacitySlider.target = self opacitySlider.action = #selector(sliderValueChanged(_:)) opacitySlider.isContinuous = false cropVC = KMDesignButton.init(withType: .Text) cropBox.contentView = cropVC?.view cropBox.fillColor = NSColor.clear cropVC?.target = self cropVC?.action = #selector(cutImageAction) cropVC?.button(type: .Sec, size: .m) cropVC?.stringValue = NSLocalizedString("Crop", comment: "") cropVC?.borderColor = KMAppearance.Interactive.s0Color() cropVC?.background = KMAppearance.Layout.l1Color() cropVC?.background_hov = KMAppearance.Layout.l1Color() cropVC?.background_focus = KMAppearance.Layout.l1Color() cropVC?.textColor = KMAppearance.Layout.h1Color() cropVC?.textColor_hov = KMAppearance.Layout.h1Color() cropVC?.textColor_focus = KMAppearance.Layout.h1Color() cropVC?.updateUI() confirmVC = KMDesignButton.init(withType: .Text) confirmBox.contentView = confirmVC?.view confirmBox.fillColor = NSColor.clear confirmVC?.target = self confirmVC?.action = #selector(confirmVCImageAction) confirmVC?.button(type: .Cta, size: .m) confirmVC?.stringValue = NSLocalizedString("Confirm", comment: "") // confirmVC?.borderColor = KMAppearance.Interactive.s0Color() // confirmVC?.background = KMAppearance.Layout.l1Color() // confirmVC?.background_hov = KMAppearance.Layout.l1Color() // confirmVC?.background_focus = KMAppearance.Layout.l1Color() // confirmVC?.textColor = KMAppearance.Layout.h1Color() // confirmVC?.textColor_hov = KMAppearance.Layout.h1Color() // confirmVC?.textColor_focus = KMAppearance.Layout.h1Color() confirmVC?.updateUI() cancelVC = KMDesignButton.init(withType: .Text) cancelBox.contentView = cancelVC?.view cancelBox.fillColor = NSColor.clear cancelVC?.target = self cancelVC?.action = #selector(cancelCutImageAction) cancelVC?.button(type: .Sec, size: .m) cancelVC?.stringValue = NSLocalizedString("Cancel", comment: "") cancelVC?.borderColor = KMAppearance.Interactive.s0Color() cancelVC?.background = KMAppearance.Layout.l1Color() cancelVC?.background_hov = KMAppearance.Layout.l1Color() cancelVC?.background_focus = KMAppearance.Layout.l1Color() cancelVC?.textColor = KMAppearance.Layout.h1Color() cancelVC?.textColor_hov = KMAppearance.Layout.h1Color() cancelVC?.textColor_focus = KMAppearance.Layout.h1Color() cancelVC?.updateUI() replaceVC = KMDesignButton.init(withType: .Text) replaceBox.contentView = replaceVC?.view replaceBox.fillColor = NSColor.clear replaceVC?.target = self replaceVC?.action = #selector(replaceImageAction) replaceVC?.button(type: .Sec, size: .m) replaceVC?.stringValue = NSLocalizedString("Replace", comment: "") replaceVC?.borderColor = KMAppearance.Interactive.s0Color() replaceVC?.borderColor_hov = KMAppearance.Interactive.s0Color() replaceVC?.borderColor_disabled = KMAppearance.Interactive.s0Color() replaceVC?.background = KMAppearance.Layout.l1Color() replaceVC?.background_hov = KMAppearance.Layout.l1Color() replaceVC?.background_focus = KMAppearance.Layout.l1Color() replaceVC?.background_disabled = KMAppearance.Layout.l1Color() replaceVC?.textColor = KMAppearance.Layout.h1Color() replaceVC?.textColor_hov = KMAppearance.Layout.h1Color() replaceVC?.textColor_focus = KMAppearance.Layout.h1Color() replaceVC?.updateUI() exportVC = KMDesignButton.init(withType: .Text) exportBox.contentView = exportVC?.view exportBox.fillColor = NSColor.clear exportVC?.target = self exportVC?.action = #selector(exportImageAction) exportVC?.button(type: .Sec, size: .m) exportVC?.stringValue = NSLocalizedString("Export", comment: "") exportVC?.borderColor = KMAppearance.Interactive.s0Color() exportVC?.borderColor_hov = KMAppearance.Interactive.s0Color() exportVC?.borderColor_disabled = KMAppearance.Interactive.s0Color() exportVC?.background = KMAppearance.Layout.l1Color() exportVC?.background_hov = KMAppearance.Layout.l1Color() exportVC?.background_focus = KMAppearance.Layout.l1Color() exportVC?.background_disabled = KMAppearance.Layout.l1Color() exportVC?.textColor = KMAppearance.Layout.h1Color() exportVC?.textColor_hov = KMAppearance.Layout.h1Color() exportVC?.textColor_focus = KMAppearance.Layout.h1Color() exportVC?.updateUI() self.noTitleLabel.textColor = KMAppearance.Layout.h1Color() self.noTitleLabel.font = NSFont.SFProTextRegularFont(14) self.noImageView.image = NSImage(named: "No_addimage") self.noImageView.alphaValue = 0.4 // self.noSubtitleLabel.stringValue = NSLocalizedString("Add Image", comment: "") let string = self.noSubtitleLabel.stringValue let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineHeightMultiple = 1.32 paragraphStyle.alignment = .center self.noSubtitleLabel.attributedStringValue = NSMutableAttributedString(string: NSLocalizedString(string, comment: ""), attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle, .foregroundColor : NSColor.km_init(hex: "#94989C"), NSAttributedString.Key.font: NSFont.SFProTextRegularFont(12.0)]) self.noBackgroundView.backgroundColor(NSColor.km_init(hex: "#F7F8FA")) } func updateLanguage() { let areas = self.editingAreas if imagesAreas.count > 0 && imagesAreas.count != areas.count { //多选图片跟文字 self.titleLabel.stringValue = NSLocalizedString("General Properties", comment: "") } else { self.titleLabel.stringValue = NSLocalizedString("Image", comment: "") } self.noTitleLabel.stringValue = NSLocalizedString("Add Image", comment: "") self.opacityTitleLabel.stringValue = NSLocalizedString("Opacity", comment: "") self.cropVC?.stringValue = NSLocalizedString("Crop", comment: "") self.confirmVC?.stringValue = NSLocalizedString("Confirm", comment: "") self.cancelVC?.stringValue = NSLocalizedString("Cancel", comment: "") self.replaceVC?.stringValue = NSLocalizedString("Replace", comment: "") self.exportVC?.stringValue = NSLocalizedString("Export", comment: "") } func reloadData() { imagesAreas = [] if self.editingAreas.count > 0 { self.noBackgroundView.isHidden = true let areas = self.editingAreas self.alignmentView.editingAreas = areas for i in 0 ... areas.count-1 { if areas[i] is CPDFEditImageArea { imagesAreas.append(areas[i] as! CPDFEditImageArea) } } if imagesAreas.count == 1 && imagesAreas.count == areas.count{ //单个图片 self.listView.selectImageAreas = imagesAreas.first self.headerBox.isHidden = false self.headerBoxHeight.constant = 176 self.headerBoxMaginWidthConstraint.constant = 8 self.imageBox.isHidden = false self.imageBoxHeight.constant = 88 self.opacityBox.isHidden = false self.opacityBoxHeight.constant = 56 self.opacityBoxBottomMaginConstraint.constant = 16 self.opacityBoxTopConstraint.constant = 16 self.buttonBox.isHidden = false // self.cropBox.isHidden = false // self.cancelBox.isHidden = false // self.replaceBox.isHidden = false self.buttonBoxHeight.constant = 112 self.editImageView.image = self.listView.selectImageAreas.thumbnailImage self.alignmentViewTopConstraint.constant = 16 let opacity: CGFloat = self.listView.opacity(for: imagesAreas.first) self.updateImageAreasOpacity(opacity: opacity, state: .ended, needListView: false) } else if imagesAreas.count > 1 && imagesAreas.count == areas.count { //多选图片 self.headerBox.isHidden = false self.headerBoxHeight.constant = 82 self.headerBoxMaginWidthConstraint.constant = 0 self.imageBox.isHidden = true self.imageBoxHeight.constant = 0 self.opacityBox.isHidden = false self.opacityBoxHeight.constant = 56 self.opacityBoxBottomMaginConstraint.constant = 0 self.opacityBoxTopConstraint.constant = 0 self.buttonBox.isHidden = false // self.cropBox.isHidden = true // self.cancelBox.isHidden = true // self.replaceBox.isHidden = true self.buttonBoxHeight.constant = 0 self.alignmentViewTopConstraint.constant = 16 var opacity = self.listView.opacity(for: imagesAreas.first) for area in imagesAreas { let newOpacity = self.listView.opacity(for: area) if (opacity < newOpacity) { opacity = newOpacity } } self.updateImageAreasOpacity(opacity: opacity, state: .ended, needListView: false) } else if imagesAreas.count > 0 && imagesAreas.count != areas.count { //多选图片跟文字 self.opacityBoxBottomMaginConstraint.constant = 0 self.headerBoxMaginWidthConstraint.constant = 0 self.alignmentViewTopConstraint.constant = 0 self.opacityBoxTopConstraint.constant = 0 // self.headerBox.isHidden = true self.headerBoxHeight.constant = 48 self.imageBox.isHidden = true self.imageBoxHeight.constant = 0 self.opacityBox.isHidden = true self.opacityBoxHeight.constant = 0 self.buttonBox.isHidden = true self.buttonBoxHeight.constant = 0 } self.updateLanguage() } else { // self.updateButtonState(hidden: true) // self.editImageView.image = NSImage() self.noBackgroundView.isHidden = false } } func updateButtonState(hidden: Bool) { if hidden { self.cancelBox.isHidden = true self.confirmBox.isHidden = true self.cropBox.isHidden = false self.replaceVC?.enabled = true self.exportVC?.enabled = true self.opacitySlider.isEnabled = true self.opacityVC?.enabled = true self.rotateLeftVC?.button.isEnabled = true self.rotateLeftVC?.view.alphaValue = 1.0 self.rotateRightVC?.button.isEnabled = true self.rotateRightVC?.view.alphaValue = 1.0 self.flipVerticalVC?.button.isEnabled = true self.flipVerticalVC?.view.alphaValue = 1.0 self.flipHorizontalVC?.button.isEnabled = true self.flipHorizontalVC?.view.alphaValue = 1.0 } else { self.cancelBox.isHidden = false self.confirmBox.isHidden = false self.cropBox.isHidden = true self.replaceVC?.enabled = false self.exportVC?.enabled = false self.opacitySlider.isEnabled = false self.opacityVC?.enabled = false self.rotateLeftVC?.button.isEnabled = false self.rotateLeftVC?.view.alphaValue = 0.5 self.rotateRightVC?.button.isEnabled = false self.rotateRightVC?.view.alphaValue = 0.5 self.flipVerticalVC?.button.isEnabled = false self.flipVerticalVC?.view.alphaValue = 0.5 self.flipHorizontalVC?.button.isEnabled = false self.flipHorizontalVC?.view.alphaValue = 0.5 } self.reloadData() if self.noBackgroundView.isHidden == false { self.opacityVC?.enabled = false } } func updateImageAreasOpacity(opacity: CGFloat, state: KMOperationState, needListView: Bool = true) { if self.editingAreas.count >= 1 { if needListView { for area in imagesAreas { self.listView.setOpacityEditArea(area, opacity: opacity) } } // self.listView.editingAreas()!.count == 1 && if (self.listView.editingAreas()?.first is CPDFEditImageArea) { self.listView.selectImageAreas = self.listView.editingAreas()!.first as? CPDFEditImageArea self.editImageView.image = self.listView.selectImageAreas.thumbnailImage self.opacitySlider.objectValue = self.listView.opacity(for: self.listView.selectImageAreas) self.opacityVC?.stringValue = Int(opacity * 100).description + "%" self.editImageView.alphaValue = opacity } } } private func changeAreasAlign(areas:[Any],newBounds:[String]) { var oldBounds : [String] = [] for i in 0 ... areas.count-1 { let area : CPDFEditArea = areas[i] as! CPDFEditArea oldBounds.append(NSStringFromRect(area.bounds)) self.listView.setBoundsEditArea(area, withBounds: NSRectFromString(newBounds[i])) } self.listView.setNeedsDisplayForVisiblePages() } } extension KMEditImagePropertyViewController: KMSelectPopButtonDelegate { func km_comboBoxSelectionDidChange(_ obj: KMDesignSelect) { if obj == opacityVC { KMPrint("km_comboBoxSelectionDidChange") let index = obj.indexOfSelectedItem var string = obj.items[index] string = string.replacingOccurrences(of: "%", with: "") let value = CGFloat(Float(string)! * 0.01) self.updateImageAreasOpacity(opacity: value, state: .changed) } } func km_controlTextDidEndEditing(_ obj: KMDesignSelect) { if obj == opacityVC { KMPrint("km_comboBoxSelectionDidChange") let index = obj.indexOfSelectedItem var string = obj.items[index] string = string.replacingOccurrences(of: "%", with: "") let value = CGFloat(Float(string)! * 0.01) self.updateImageAreasOpacity(opacity: value, state: .ended) } } } //MARK: - Action extension KMEditImagePropertyViewController { @objc func sliderValueChanged(_ sender: NSSlider) { let sliderValue = sender.floatValue self.updateImageAreasOpacity(opacity:CGFloat(sliderValue), state: .changed) } @IBAction func rightRotationImageAction(_ sender: Any) { if self.listView.editingAreas()?.count ?? 0 < 1 { return } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Rotate"]) let areas = self.listView.editingAreas() if areas!.count == 1 && (areas!.first is CPDFEditImageArea) { let imageArea = areas!.first as! CPDFEditImageArea self.listView.rotate(with: imageArea, rotate: 90) self.listView.selectImageAreas = imageArea self.editImageView.image = self.listView.selectImageAreas.thumbnailImage } else if areas!.count > 1 { for imagesArea in imagesAreas { self.listView.rotate(with: imagesArea, rotate: 90) } } self.delegate?.editImagePropertyViewControllerDidChanged(controller: self, type: .rotate) } @IBAction func leftRotationImageAction(_ sender: Any) { if self.listView.editingAreas()?.count ?? 0 < 1 { return } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Rotate"]) let areas = self.listView.editingAreas() if areas!.count == 1 && (areas!.first is CPDFEditImageArea) { self.listView.rotate(with: self.listView.selectImageAreas, rotate: -90) if self.listView.editingAreas()!.count == 1 && (self.listView.editingAreas()!.first is CPDFEditImageArea) { self.listView.selectImageAreas = self.listView.editingAreas()!.first as? CPDFEditImageArea } self.editImageView.image = self.listView.selectImageAreas.thumbnailImage } else { for imagesArea in imagesAreas { self.listView.rotate(with: imagesArea, rotate: -90) } } self.delegate?.editImagePropertyViewControllerDidChanged(controller: self, type: .rotate) } @IBAction func flipHorizontalImageAction(_ sender: Any) { if self.listView.editingAreas()?.count ?? 0 < 1 { return } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Reverse"]) let areas = self.listView.editingAreas() if areas != nil { for item in areas! { if item is CPDFEditImageArea { self.listView.horizontalMirror(with: item as? CPDFEditImageArea) if areas?.count == 1 { self.editImageView.image = (item as AnyObject).thumbnailImage } } else { for imagesArea in imagesAreas { self.listView.horizontalMirror(with: imagesArea) } } } } self.delegate?.editImagePropertyViewControllerDidChanged(controller: self, type: .flip) } @IBAction func flipVerticalImageAction(_ sender: Any) { if self.listView.editingAreas()?.count ?? 0 < 1 { return } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Reverse"]) let areas = self.listView.editingAreas() if areas != nil { for item in areas! { if item is CPDFEditImageArea { self.listView.verticalMirror(with: item as? CPDFEditImageArea) self.editImageView.image = self.listView.selectImageAreas.thumbnailImage } else { for imagesArea in imagesAreas { self.listView.verticalMirror(with: imagesArea) } } } } self.delegate?.editImagePropertyViewControllerDidChanged(controller: self, type: .flip) } @IBAction func cutImageAction(_ sender: Any) { if self.listView.selectImageAreas == nil { return } self.listView.isEditImage = true self.listView.enterCrop(with: self.listView.selectImageAreas) self.updateButtonState(hidden: false) } @IBAction func confirmVCImageAction(_ sender: Any) { if self.listView.selectImageAreas == nil || self.listView.cropAreas == nil { return } self.listView.cropEditImageArea(self.listView.selectImageAreas, withBounds: self.listView.cropAreas.cropRect) self.cancelCutImageAction(cancelVC?.button as Any) } @IBAction func cancelCutImageAction(_ sender: Any) { if self.listView.selectImageAreas == nil { return } self.listView.exitCrop(with: self.listView.selectImageAreas) self.listView.cropAreas = nil self.listView.isEditImage = false self.updateButtonState(hidden: true) } @IBAction func restoreCutImageAction(_ sender: Any) { if self.listView.selectImageAreas == nil { return } self.listView.resetCrop(with: self.listView.selectImageAreas) } @IBAction func replaceImageAction(_ sender: NSButton) { if self.listView.selectImageAreas == nil { return } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Replace"]) let panel = NSOpenPanel() panel.allowsMultipleSelection = false panel.allowedFileTypes = ["png","jpg"] panel.beginSheetModal(for: NSApp.mainWindow!) { response in if response == .OK { let openPath = panel.url?.path // let s = self.listView.extractImage(with: self.selectImageAreas, toImagePath: openPath!) let s = self.listView.replace(self.listView.selectImageAreas, imagePath: openPath!) if s { } } } } // @available(macOS 13.0, *) @IBAction func exportImageAction(_ sender: Any) { if self.listView.selectImageAreas == nil { return } if imagesAreas.count == 1 { let panel = NSSavePanel() panel.nameFieldStringValue = "\(NSLocalizedString("Untitled", comment: "")).jpg" // let button = NSButton.init(checkboxWithTitle: NSLocalizedString("Open the document after saving", comment: ""), target: nil, action: nil) // button.state = .on // panel.accessoryView = button panel.isExtensionHidden = true let response = panel.runModal() if response == .OK { let url = panel.url if FileManager.default.fileExists(atPath: url!.path) { try?FileManager.default.removeItem(atPath: url!.path) } let result = self.listView.extractImage(with: self.listView.selectImageAreas, toImagePath: url!.path) if result { // if button.state == .on { /// 开启文档 // NSWorkspace.shared.openFile(url!.path) NSWorkspace.shared.activateFileViewerSelecting([url!]) // } else { // // } } } } else if imagesAreas.count > 1 { let panel = NSOpenPanel() panel.canChooseFiles = false panel.canChooseDirectories = true panel.canCreateDirectories = true panel.allowsMultipleSelection = false panel.beginSheetModal(for: NSApp.mainWindow!) { response in if response == .OK { let outputURL = panel.url let s = self.listView.document.documentURL.lastPathComponent let folderPath = self.listView.document.documentURL.deletingPathExtension().lastPathComponent + "_extract" var filePath = outputURL?.path.stringByAppendingPathComponent(folderPath) var i = 1 let testFilePath = filePath while FileManager.default.fileExists(atPath: filePath!) { filePath = testFilePath! + "\(i)" i = i + 1 } try? FileManager.default.createDirectory(atPath: filePath!, withIntermediateDirectories: false, attributes: nil) var saveURLs : [URL] = [] for j in 0 ... self.imagesAreas.count-1 { let documentFileName = self.listView.document.documentURL.deletingPathExtension().lastPathComponent var outPath = filePath! outPath = outPath.stringByAppendingPathComponent(documentFileName) outPath = outPath + "page \(j+1)" outPath = outPath.stringByAppendingPathExtension("jpg") let result = self.listView.extractImage(with: self.imagesAreas[j], toImagePath: outPath) if result { saveURLs.append(URL(fileURLWithPath: outPath)) } } NSWorkspace.shared.activateFileViewerSelecting(saveURLs) } } } } } class CustomSliderCell: NSSliderCell { var knobImage: NSImage? override func drawKnob(_ knobRect: NSRect) { if let image = knobImage { let imageSize = NSSize(width: knobRect.size.height, height: knobRect.size.height) let imageRect = NSRect(origin: knobRect.origin, size: imageSize) image.draw(in: imageRect) } else { super.drawKnob(knobRect) } } }