// // KMCropPropertyController.swift // PDF Reader Pro // // Created by Niehaoyu on 2024/11/20. // import Cocoa import KMComponentLibrary @objc protocol KMCropPropertyControllerDelegate: AnyObject { @objc optional func kmCropControllerDidCrop(_ controller: KMCropPropertyController, _ cropRect: CGRect, _ view: KMPageRangeSelectView) @objc optional func kmCropControllerDidCropSeparate(_ controller: KMCropPropertyController, _ view: KMPageRangeSelectView) @objc optional func kmCropControllerDidCropAuto(_ controller: KMCropPropertyController, _ view: KMPageRangeSelectView) } class KMCropPropertyController: NSViewController { @IBOutlet var contendView: NSView! //White Margin @IBOutlet var whiteMarginBGView: NSView! @IBOutlet var whiteMarginLabel: NSTextField! @IBOutlet var separateLabel: NSTextField! @IBOutlet var separateTip: ComponentToolTipsHelp! @IBOutlet var separateSwitch: ComponentSwitch! @IBOutlet var autoLabel: NSTextField! @IBOutlet var autoTipsView: ComponentToolTipsHelp! @IBOutlet var autoSwitch: ComponentSwitch! //PageSize @IBOutlet var pageSizeBGView: NSView! @IBOutlet var pageSizeLabel: NSTextField! @IBOutlet var sizeSyncButton: ComponentButton! @IBOutlet var sizeWidthInput: ComponentInputNumber! @IBOutlet var sizeHeightInput: ComponentInputNumber! //PageMargin @IBOutlet var pageMarginBGView: NSView! @IBOutlet var pageMarginLabel: NSTextField! @IBOutlet var pageLeftInput: ComponentInputNumber! @IBOutlet var pageTopInput: ComponentInputNumber! @IBOutlet var pageRightInput: ComponentInputNumber! @IBOutlet var pageBottomInput: ComponentInputNumber! //PageRange @IBOutlet var pageRangeBGView: NSView! @IBOutlet var pageRangeLabel: NSTextField! @IBOutlet var pangeRangeSelectView: KMPageRangeSelectView! @IBOutlet var cropButton: ComponentButton! private var _syncChangeBounds: Bool = false //同步修改宽高 weak open var delegate: KMCropPropertyControllerDelegate? public var pdfView: CPDFListView? public var pageBounds: CGRect = .zero var pageCropBounds: CGRect = .zero override func viewDidLoad() { super.viewDidLoad() // Do view setup here. if UserDefaults.standard.object(forKey: "CropSyncChangeBoundsKey") == nil { UserDefaults.standard.setValue(true, forKey: "CropSyncChangeBoundsKey") } syncChangeBounds = UserDefaults.standard.bool(forKey: "CropSyncChangeBoundsKey") setupProperty() reloadData() } //MARK: - Setter and Getter public var syncChangeBounds : Bool { get { return _syncChangeBounds } set { _syncChangeBounds = newValue UserDefaults.standard.setValue(_syncChangeBounds, forKey: "CropSyncChangeBoundsKey") } } public func recoverEnable() -> Bool { guard let pdfView = self.pdfView else { return false } //PageRange if CGRectEqualToRect(pdfView.selectionRect, self.pageBounds) { } else { return true } return false } public func cropEnable() -> Bool { return cropButton.properties.isDisabled ? false : true } func setupProperty() { //White Margin whiteMarginLabel.stringValue = KMLocalizedString("Crop White Margins") whiteMarginLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2") whiteMarginLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium") separateLabel.stringValue = KMLocalizedString("Separate") separateLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("comp-form/colorText-label") separateLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-regular") separateSwitch.properties = ComponentSwitchProperty(size: .s, open: false, isDisabled: false) separateSwitch.setTarget(self, action: #selector(switchAction(_:))) autoLabel.stringValue = KMLocalizedString("Auto") autoLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("comp-form/colorText-label") autoLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-regular") separateTip.toolTip = KMLocalizedString("separateTip tooltips") autoTipsView.toolTip = KMLocalizedString("autoTipsView tooltips") autoSwitch.properties = ComponentSwitchProperty(size: .s, open: false, isDisabled: false) autoSwitch.setTarget(self, action: #selector(switchAction(_:))) //PageSize whiteMarginLabel.stringValue = KMLocalizedString("Crop Page Size") whiteMarginLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2") whiteMarginLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium") sizeSyncButton.properties = ComponentButtonProperty(type: .text_gray, size: .xxs, onlyIcon: true, icon: NSImage(named: "sync_Change_unlock"), keepPressState: true) sizeSyncButton.properties.propertyInfo.leftIcon_press = NSImage(named: "sync_Change_lock") sizeSyncButton.setTarget(self, action: #selector(sizeSyncButtonClicked(_:))) sizeSyncButton.reloadData() sizeWidthInput.properties = ComponentInputNumberProperty(alignment: .center, size: .s, state: .normal, showPrefix: true, leftIcon: NSImage(named: "w_icon"), minSize: 0, maxSize: 1000, text:"100") sizeWidthInput.delegate = self sizeHeightInput.properties = ComponentInputNumberProperty(alignment: .center, size: .s, state: .normal, showPrefix: true, leftIcon: NSImage(named: "h_icon"), minSize: 0, maxSize: 1000, text:"100") sizeHeightInput.delegate = self //PageMargin whiteMarginLabel.stringValue = KMLocalizedString("Crop Page Margins") whiteMarginLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2") whiteMarginLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium") pageLeftInput.properties = ComponentInputNumberProperty(size: .s, state: .normal, minSize: 0, maxSize: 1000, text:"0") pageTopInput.properties = ComponentInputNumberProperty(size: .s, state: .normal, minSize: 0, maxSize: 1000, text:"0") pageRightInput.properties = ComponentInputNumberProperty(size: .s, state: .normal, minSize: 0, maxSize: 1000, text:"0") pageBottomInput.properties = ComponentInputNumberProperty(size: .s, state: .normal, minSize: 0, maxSize: 1000, text:"0") pageLeftInput.delegate = self pageTopInput.delegate = self pageRightInput.delegate = self pageBottomInput.delegate = self //PageRange pageRangeLabel.stringValue = KMLocalizedString("Page Range") pageRangeLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2") pageRangeLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium") cropButton.properties = ComponentButtonProperty(type: .primary, size: .m, buttonText: KMLocalizedString("Apply"), keepPressState: false) cropButton.setTarget(self, action: #selector(cropButtonClicked(_:))) } func reloadData() { //White Margin separateSwitch.properties.open = KMCropManager.defaultManager.cropSeparateOn separateSwitch.reloadData() autoSwitch.properties.open = KMCropManager.defaultManager.cropAutoOn autoSwitch.reloadData() guard let pdfView = self.pdfView else { return } guard let page = pdfView.currentSelectionPage() else { return } let pageBounds = page.bounds let selectionRect = pdfView.selectionRect //PageSize sizeWidthInput.properties.maxSize = Int(pageBounds.size.width) sizeWidthInput.properties.text = String(format: "%.0f", selectionRect.size.width) sizeWidthInput.reloadData() sizeHeightInput.properties.maxSize = Int(pageBounds.size.height) sizeHeightInput.properties.text = String(format: "%.0f", selectionRect.size.height) sizeHeightInput.reloadData() if syncChangeBounds { sizeSyncButton.properties.state = .pressed } else { sizeSyncButton.properties.state = .normal } sizeSyncButton.reloadData() //PageMargin pageLeftInput.properties.maxSize = Int(pageBounds.size.width) pageLeftInput.properties.text = String(format: "%.0f", selectionRect.origin.x) pageLeftInput.reloadData() pageRightInput.properties.maxSize = Int(pageBounds.size.width) pageRightInput.properties.text = String(format: "%.0f", pageBounds.size.width - CGRectGetMaxX(selectionRect)) pageRightInput.reloadData() pageTopInput.properties.maxSize = Int(pageBounds.size.height) pageTopInput.properties.text = String(format: "%.0f", pageBounds.size.height - CGRectGetMaxY(selectionRect)) pageTopInput.reloadData() pageBottomInput.properties.maxSize = Int(pageBounds.size.height) pageBottomInput.properties.text = String(format: "%.0f", selectionRect.origin.y) pageBottomInput.reloadData() //PageRange if CGRectEqualToRect(pageCropBounds, selectionRect) { cropButton.properties.isDisabled = true } else { cropButton.properties.isDisabled = false } cropButton.reloadData() self.pageBounds = pageBounds } //MARK: - Action @objc func sizeSyncButtonClicked(_ sender: ComponentButton) { syncChangeBounds = !syncChangeBounds reloadData() } @objc func cropButtonClicked(_ sender: ComponentButton) { if KMCropManager.defaultManager.cropSeparateOn { delegate?.kmCropControllerDidCropSeparate?(self, pangeRangeSelectView) } else if KMCropManager.defaultManager.cropAutoOn { delegate?.kmCropControllerDidCropAuto?(self, pangeRangeSelectView) } else { delegate?.kmCropControllerDidCrop?(self, pdfView?.selectionRect ?? CGRectZero, pangeRangeSelectView) } } @objc func switchAction(_ sender: ComponentSwitch) { guard let pdfView = self.pdfView else { return } guard let page = pdfView.document.page(at: 0) else { return } if sender == separateSwitch { KMCropManager.defaultManager.cropSeparateOn = sender.properties.open KMCropManager.defaultManager.cropAutoOn = false KMCropManager.defaultManager.cropRect = nil let rect = KMCropTools.getPageForegroundBox(page) pdfView.selectionRect = rect pdfView.setNeedsDisplayForVisiblePages() } else if sender == autoSwitch { KMCropManager.defaultManager.cropAutoOn = sender.properties.open KMCropManager.defaultManager.cropSeparateOn = false KMCropManager.defaultManager.cropRect = nil let rect = KMCropTools.getPageForegroundBox(page) pdfView.selectionRect = rect pdfView.setNeedsDisplayForVisiblePages() } reloadData() } } //MARK: - ComponentInputNumberDelegate extension KMCropPropertyController: ComponentInputNumberDelegate { func componentInputNumberDidValueChanged(inputNumber: ComponentInputNumber?) { guard let pdfView = self.pdfView else { return } guard let page = pdfView.currentSelectionPage() else { return } let pageBounds = page.bounds var value: CGFloat = 0 if let text = inputNumber?.properties.text { value = text.stringToCGFloat() } var rect = pdfView.selectionRect if inputNumber == sizeWidthInput { if syncChangeBounds { var scale: CGFloat = 0 if rect.size.width != 0 { scale = value / rect.size.width } rect.size.height *= scale } rect.size.width = value } else if inputNumber == sizeHeightInput { if syncChangeBounds { var scale: CGFloat = 0 if rect.size.height != 0 { scale = value / rect.size.height } rect.size.width *= scale } rect.size.height = value } else if inputNumber == pageLeftInput { rect.origin.x = value rect.size.width -= (value - pdfView.selectionRect.origin.x) } else if inputNumber == pageRightInput { rect.size.width = pageBounds.size.width - rect.origin.x - value } else if inputNumber == pageTopInput { rect.size.height = pageBounds.size.height - rect.origin.y - value } else if inputNumber == pageBottomInput { rect.origin.y = value rect.size.height -= (value - pdfView.selectionRect.origin.y) } pdfView.selectionRect = rect pdfView.setNeedsDisplayForVisiblePages() KMCropManager.defaultManager.cropRect = rect KMCropManager.defaultManager.cropAutoOn = false KMCropManager.defaultManager.cropSeparateOn = false reloadData() } }