123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874 |
- //
- // KMNWatermarkPropertyController.swift
- // PDF Reader Pro
- //
- // Created by Niehaoyu on 2024/11/1.
- //
- import Cocoa
- import KMComponentLibrary
- @objc protocol KMNWatermarkPropertyControllerDelegate: AnyObject {
-
- @objc optional func watermarkPropertyControllerDidRemoveWatermark(_ controller: KMNWatermarkPropertyController, _ type: CPDFWatermarkType)
-
- //水印数据有更新
- @objc optional func watermarkPropertyControllerDidUpdate(_ controller: KMNWatermarkPropertyController)
-
- //切换到模板界面
- @objc optional func watermarkPropertyControllerDidChangetoTemplate(_ controller: KMNWatermarkPropertyController)
-
- //成功保存到模板
- @objc optional func watermarkPropertyControllerSaveTemplateSuccess(_ controller: KMNWatermarkPropertyController, _ data: KMPDFWatermarkData)
- //取消修改模板信息
- @objc optional func watermarkPropertyControllerCancelTemplateEdit(_ controller: KMNWatermarkPropertyController)
- }
- class KMNWatermarkPropertyController: NSViewController {
-
- @IBOutlet var contendView: NSView!
- @IBOutlet var leftTopButton: ComponentButton!
- @IBOutlet var titleLabel: NSTextField!
- @IBOutlet var templateButton: ComponentButton!
-
- @IBOutlet var typeTabsBGView: NSView!
- @IBOutlet var typeTabs: ComponentTabs!
-
- @IBOutlet var infoContendView: NSView!
- @IBOutlet var infoScrollView: KMScrollView!
- @IBOutlet var infoScrollTopConst: NSLayoutConstraint!
- @IBOutlet var infoContendBottomConst: NSLayoutConstraint!
-
- //Text
- @IBOutlet var textBGView: NSView!
- @IBOutlet var text_textareaView: ComponentTextarea!
- @IBOutlet var fontNameSelect: ComponentSelect!
- @IBOutlet var fontStyleSelect: ComponentSelect!
- @IBOutlet var fontSizeSelect: ComponentSelect!
- @IBOutlet var fontColorGroup: ComponentCColorGroup!
-
- //File
- @IBOutlet var fileBGView: NSView!
- @IBOutlet var fileInputView: ComponentInput!
- @IBOutlet var fileInputAddonView: ComponentInputAddon!
-
- //Appearance
- @IBOutlet var appearanceBGView: NSView!
- @IBOutlet var appearanceLabel: NSTextField!
- @IBOutlet var appearance_RotateSelect: ComponentSelect!
- @IBOutlet var appearance_OpacitySelect: ComponentSelect!
- @IBOutlet var appearanceScaleCheckbox: ComponentCheckBox!
- @IBOutlet var appearanceScaleSelect: ComponentSelect!
- @IBOutlet var appearanceTopPageRadio: ComponentRadio!
- @IBOutlet var appearanceBottomPageRadio: ComponentRadio!
- @IBOutlet var appearanceBGTopConst: NSLayoutConstraint!
-
- //Position
- @IBOutlet var positionBGView: NSView!
- @IBOutlet var positionLabel: NSTextField!
- @IBOutlet var positionItemView: ComponentCPosition!
- @IBOutlet var positionXInput: ComponentInputNumber!
- @IBOutlet var positionYInput: ComponentInputNumber!
-
- @IBOutlet var positionTileCheckbox: ComponentCheckBox!
- @IBOutlet var positionTileHorImage: NSImageView!
- @IBOutlet var positionTileVertImage: NSImageView!
- @IBOutlet var positionTileHoriInput: ComponentInputNumber!
- @IBOutlet var positionTileVertInput: ComponentInputNumber!
-
- //Save
- @IBOutlet var saveTemplateBGView: NSView!
- @IBOutlet var saveButton: ComponentButton!
-
- private var textTabProperty = ComponentTabsProperty(tabsType: .underline_Fill, state: .normal, showIcon: false, title: KMLocalizedString("Text"))
- private var fileTabProperty = ComponentTabsProperty(tabsType: .underline_Fill, state: .normal, showIcon: false, title: KMLocalizedString("File"))
-
- private var familyNames = CPDFFont.familyNames
-
- var watermarkData: KMPDFWatermarkData = KMWatermarkManager.defaultManager.defaultWatermarkData
-
- public var editSubType: KMPDFEditSubModeType = .add
- public var isInBatchMode: Bool = false
-
- var originalDataDict: Dictionary<String, Any>?
-
- weak open var delegate: KMNWatermarkPropertyControllerDelegate?
- //MARK: - func
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do view setup here.
-
- infoScrollView.documentView = infoContendView
- infoScrollView.scrollerStyle = .overlay
- infoScrollView.layout()
-
- setupProperty()
-
- reloadData()
-
- refreshScrollView()
- }
-
- func setupProperty() {
- contendView.wantsLayer = true
- contendView.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle").cgColor
-
- titleLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- titleLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-bold")
-
- leftTopButton.properties = ComponentButtonProperty(type: .text_gray, size: .xxs, onlyIcon: true, icon: NSImage(named: "watermark_arrowLeft"), keepPressState: false)
- leftTopButton.setTarget(self, action: #selector(leftTopButtonClicked(_:)))
- templateButton.properties = ComponentButtonProperty(type: .text_gray, size: .xxs, onlyIcon: true, icon: NSImage(named: "icon_wm_template"), keepPressState: false)
- templateButton.setTarget(self, action: #selector(templateButtonClicked(_:)))
-
- typeTabs.updateItemProperty([textTabProperty, fileTabProperty])
- typeTabs.delegate = self
-
-
- //Text
- text_textareaView.properties = ComponentTextareaProperty(size: .s, placeholderString: KMLocalizedString("Please enter..."), totalCount: -1, text: "")
- text_textareaView.delegate = self
-
- fontNameSelect.properties = ComponentSelectProperties(size: .s,
- state: .normal,
- text: "")
-
- var menuItemArr: [ComponentMenuitemProperty] = []
- for string in familyNames {
- let item = ComponentMenuitemProperty(type: .normal, text: string, identifier: string)
- menuItemArr.append(item)
- }
- fontNameSelect.updateMenuItemsArr(menuItemArr)
- fontNameSelect.selectItemAtIndex(0)
- fontNameSelect.delegate = self
-
- fontStyleSelect.properties = ComponentSelectProperties(size: .s,
- state: .normal,
- text: "")
- fontStyleSelect.delegate = self
-
- fontSizeSelect.properties = ComponentSelectProperties(size: .s,
- state: .normal,
- creatable: true,
- text: "12 pt",
- textUnit: " pt",
- regexString: "0123456789 pt")
- var sizeItemArr: [ComponentMenuitemProperty] = []
- for string in ["6","8","10","12","14",
- "16","18","20","22","24",
- "26","28","30","32","34",
- "36","40","48","64","80",
- "96","112"] {
- let item = ComponentMenuitemProperty(type: .normal, text: string, identifier: string)
- sizeItemArr.append(item)
- }
- fontSizeSelect.updateMenuItemsArr(sizeItemArr)
- fontSizeSelect.selectItemAtIndex(0)
- fontSizeSelect.delegate = self
-
- let colorAProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMAnnotationPropertiesColorManager.manager.watermark_Colors[0])
- let colorBProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMAnnotationPropertiesColorManager.manager.watermark_Colors[1])
- let colorCProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMAnnotationPropertiesColorManager.manager.watermark_Colors[2])
- let colorDProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: false, color: KMAnnotationPropertiesColorManager.manager.watermark_Colors[3])
- let colorEProperty = ComponentCColorProperty(colorType: .color, state: .normal, isCustom: true, color: KMAnnotationPropertiesColorManager.manager.watermark_Colors[4])
-
- fontColorGroup.setUpWithColorPropertys([colorAProperty, colorBProperty, colorCProperty, colorDProperty], customItemProperty: colorEProperty)
- fontColorGroup.delegate = self
-
- //File
- fileInputView.properties = ComponentInputProperty(size: .s,
- state:.pressed ,
- placeholder: "Select Source File...",
- text: "",
- creatable: false)
- fileInputView.properties.propertyInfo.cornerRadius_topLeft = 0
- fileInputView.properties.propertyInfo.cornerRadius_topRight = 0
- fileInputView.properties.propertyInfo.cornerRadius_bottomLeft = 0
- fileInputView.properties.propertyInfo.cornerRadius_bottomRight = 0
- fileInputView.reloadData()
- fileInputView.delegate = self
-
- fileInputAddonView.properties = ComponentInputAddonProperty(size: .s,
- state: .normal,
- addOnBefore: false,
- onlyRead: false,
- addonType: .imageWithColor,
- iconImage: NSImage(named: "icon_folder"))
- fileInputAddonView.setTarget(self, action: #selector(chooseURLAction(_ :)))
-
- //Appearance
- appearanceLabel.stringValue = KMLocalizedString("Appearance")
- appearanceLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- appearanceLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
-
- appearance_RotateSelect.properties = ComponentSelectProperties(size: .s,
- state: .normal,
- creatable: true,
- text: "0°",
- textUnit: "°",
- regexString: "0123456789°-")
- var rotateItems: [ComponentMenuitemProperty] = []
- for string in ["0°", "45°", "-45°", "90°", "-90°"] {
- let item = ComponentMenuitemProperty(type: .normal, text: string)
- rotateItems.append(item)
- }
- appearance_RotateSelect.updateMenuItemsArr(rotateItems)
- appearance_RotateSelect.delegate = self
-
- appearance_OpacitySelect.properties = ComponentSelectProperties(size: .s,
- state: .normal,
- creatable: true,
- text: "100%",
- textUnit: "%",
- regexString: "0123456789%")
- var opacityItems: [ComponentMenuitemProperty] = []
- for string in ["25%", "50%", "75%", "100%"] {
- let item = ComponentMenuitemProperty(type: .normal, text: string)
- opacityItems.append(item)
- }
- appearance_OpacitySelect.updateMenuItemsArr(opacityItems)
- appearance_OpacitySelect.delegate = self
-
- appearanceScaleCheckbox.properties = ComponentCheckBoxProperty(size: .s, text: KMLocalizedString("Scale relative to target page"), checkboxType: .normal)
- appearanceScaleCheckbox.setTarget(self, action: #selector(checkBoxClicked(_:)))
-
- appearanceScaleSelect.properties = ComponentSelectProperties(size: .s,
- state: .normal,
- creatable: true,
- text: "100%",
- textUnit: "%",
- regexString: "0123456789%")
- var appearanceScaleItems: [ComponentMenuitemProperty] = []
- for string in ["25%", "50%", "75%", "100%", "125%", "150%","200%"] {
- let item = ComponentMenuitemProperty(type: .normal, text: string)
- appearanceScaleItems.append(item)
- }
- appearanceScaleSelect.updateMenuItemsArr(appearanceScaleItems)
- appearanceScaleSelect.delegate = self
-
- appearanceTopPageRadio.properties = ComponentCheckBoxProperty(size: .s, text: KMLocalizedString("At the top of the page"), checkboxType: .normal)
- appearanceTopPageRadio.setTarget(self, action: #selector(radioClicked(_:)))
-
- appearanceBottomPageRadio.properties = ComponentCheckBoxProperty(size: .s, text: KMLocalizedString("At the bottom of the page"), checkboxType: .normal)
- appearanceBottomPageRadio.setTarget(self, action: #selector(radioClicked(_:)))
-
-
- //Position
- positionLabel.stringValue = KMLocalizedString("Position (mm)")
- positionLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- positionLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
-
- positionItemView.properties = ComponentCPositionProperty(rowCount: 3, columnCount: 3, dash: false, selRow: 1, selColumn: 1)
- positionItemView.delegate = self
-
- positionXInput.properties = ComponentInputNumberProperty(alignment: .left,
- size: .s,
- minSize: -1000,
- maxSize: 1000,
- text: "0")
- positionXInput.delegate = self
-
- positionYInput.properties = ComponentInputNumberProperty(alignment: .left,
- size: .s,
- minSize: -1000,
- maxSize: 1000,
- text: "0")
- positionYInput.delegate = self
-
- positionTileCheckbox.properties = ComponentCheckBoxProperty(size: .s, text: KMLocalizedString("Tile"), checkboxType: .normal)
- positionTileCheckbox.setTarget(self, action: #selector(checkBoxClicked(_:)))
-
- positionTileHoriInput.properties = ComponentInputNumberProperty(alignment: .left,
- size: .s,
- minSize: 0,
- maxSize: 1000,
- text: "0")
- positionTileHoriInput.delegate = self
-
- positionTileVertInput.properties = ComponentInputNumberProperty(alignment: .left,
- size: .s,
- minSize: 0,
- maxSize: 1000,
- text: "0")
- positionTileVertInput.delegate = self
-
-
- //Save
- saveTemplateBGView.wantsLayer = true
- saveTemplateBGView.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle").cgColor
- saveButton.properties = ComponentButtonProperty(type: .default_tertiary, size: .m, showLeftIcon: true, buttonText: KMLocalizedString("Save as Template"), icon: NSImage(named: "icon_wm_template_save"), keepPressState: false)
- saveButton.setTarget(self, action: #selector(saveButtonClicked(_:)))
-
- }
-
- func refreshScrollView() {
- infoScrollView.contentViewSize = CGSizeMake(264, 672)
- if watermarkData.watermarkType == .text {
- infoScrollView.contentViewSize = CGSizeMake(264, 672)
- } else if watermarkData.watermarkType == .image {
- infoScrollView.contentViewSize = CGSizeMake(264, 512)
- }
- infoScrollView.scrollToTop()
- }
-
- func reloadData() {
- titleLabel.stringValue = KMLocalizedString("Add Watermark")
- leftTopButton.isHidden = true
- saveTemplateBGView.isHidden = false
- templateButton.properties.icon = NSImage(named: "icon_wm_template")
- typeTabsBGView.isHidden = false
- infoScrollTopConst.constant = 56
-
- if editSubType == .edit {
- typeTabsBGView.isHidden = true
- infoScrollTopConst.constant = 8
-
- titleLabel.stringValue = KMLocalizedString("Edit Template")
- leftTopButton.isHidden = false
- saveTemplateBGView.isHidden = true
- templateButton.properties.icon = NSImage(named: "edit_save")
- }
- templateButton.reloadData()
-
- if self.isInBatchMode {
- infoContendBottomConst.constant = 0
- saveTemplateBGView.isHidden = true
- } else {
- infoContendBottomConst.constant = 72
- saveTemplateBGView.isHidden = false
- }
-
- fileBGView.isHidden = true
- textBGView.isHidden = true
-
- textTabProperty.state = .normal
- fileTabProperty.state = .normal
-
- if watermarkData.watermarkType == .text {
- textBGView.isHidden = false
- appearanceBGTopConst.constant = 200
- textTabProperty.state = .pressed
- } else if watermarkData.watermarkType == .image {
- fileBGView.isHidden = false
- appearanceBGTopConst.constant = 48
- fileTabProperty.state = .pressed
- }
- typeTabs.refreshItems()
-
- //Text
- text_textareaView.properties.text = watermarkData.text ?? ""
- text_textareaView.reloadData()
-
- if let index = familyNames.firstIndex(of: watermarkData.fontName) {
- fontNameSelect.selectItemAtIndex(index)
- }
- fontNameSelect.properties.text = watermarkData.fontName
- fontNameSelect.reloadData()
-
- let styleNames = CPDFFont.fontNames(forFamilyName: watermarkData.fontName)
- var menuItemArr: [ComponentMenuitemProperty] = []
- for string in styleNames {
- let item = ComponentMenuitemProperty(type: .normal, text: string, identifier: string)
- menuItemArr.append(item)
- }
- fontStyleSelect.updateMenuItemsArr(menuItemArr)
- if watermarkData.fontStyle == nil {
- fontStyleSelect.selectItemAtIndex(0)
- watermarkData.fontStyle = styleNames.first
- } else {
- fontStyleSelect.properties.text = watermarkData.fontStyle
- fontStyleSelect.reloadData()
- }
-
- positionTileCheckbox.properties.isDisabled = false
-
- let fontSizeStr = String(format: "%.0f", watermarkData.fontSize)
- if let index = KMWatermarkManager.getFontSize().firstIndex(of: fontSizeStr) {
- fontSizeSelect.selectItemAtIndex(index)
- }
- fontSizeSelect.properties.text = String(format: "%.0f", watermarkData.fontSize) + " pt"
- fontSizeSelect.properties.isDisabled = false
- if watermarkData.isScale {
- fontSizeSelect.properties.isDisabled = true
- positionTileCheckbox.properties.isDisabled = true
- watermarkData.isTilePage = false
- }
- fontSizeSelect.reloadData()
-
- fontColorGroup.currentColor = watermarkData.textColor
- fontColorGroup.refreshUI()
-
- //File
- fileInputView.properties.text = watermarkData.imagePath ?? ""
- fileInputView.reloadData()
-
- //Appearance
- appearance_RotateSelect.properties.text = String(format: "%.0f", watermarkData.rotation) + "°"
- appearance_RotateSelect.reloadData()
-
- if watermarkData.opacity > 1 {
- watermarkData.opacity = 1
- }
- appearance_OpacitySelect.properties.text = String(format: "%.0f", watermarkData.opacity*100) + "%"
- appearance_OpacitySelect.reloadData()
-
- appearanceScaleCheckbox.properties.checkboxType = watermarkData.isScale ? .selected : .normal
- appearanceScaleCheckbox.reloadData()
- appearanceScaleSelect.properties.isDisabled = watermarkData.isScale ? false : true
- appearanceScaleSelect.properties.text = String(format: "%.0f", watermarkData.scale*100) + "%"
- appearanceScaleSelect.reloadData()
-
- appearanceTopPageRadio.properties.checkboxType = watermarkData.isFront ? .selected : .normal
- appearanceTopPageRadio.reloadData()
-
- appearanceBottomPageRadio.properties.checkboxType = watermarkData.isFront ? .normal : .selected
- appearanceBottomPageRadio.reloadData()
-
- //Position
- positionXInput.properties.text = String(format: "%.0f", watermarkData.tx)
- positionXInput.reloadData()
-
- positionYInput.properties.text = String(format: "%.0f", watermarkData.ty)
- positionYInput.reloadData()
-
- positionTileHoriInput.properties.text = String(format: "%.0f", watermarkData.horizontalSpacing)
-
- positionTileVertInput.properties.text = String(format: "%.0f", watermarkData.verticalSpacing)
-
- if watermarkData.isTilePage {
- positionTileHorImage.image = NSImage(named: "tile_spacing_horiz")
- positionTileVertImage.image = NSImage(named: "tile_spacing_vert")
-
- positionTileHoriInput.properties.isDisabled = false
- positionTileVertInput.properties.isDisabled = false
- } else {
- positionTileHorImage.image = NSImage(named: "tile_spacing_horiz_dis")
- positionTileVertImage.image = NSImage(named: "tile_spacing_vert_dis")
-
- positionTileHoriInput.properties.isDisabled = true
- positionTileVertInput.properties.isDisabled = true
- }
- positionTileHoriInput.reloadData()
- positionTileVertInput.reloadData()
-
- positionTileCheckbox.properties.checkboxType = watermarkData.isTilePage ? .selected : .normal
- positionTileCheckbox.reloadData()
-
- saveButton.properties.isDisabled = false
- if watermarkData.watermarkType == .text {
- if watermarkData.text?.count == 0 {
- saveButton.properties.isDisabled = true
- }
- } else if watermarkData.watermarkType == .image {
- if watermarkData.imagePath == nil {
- saveButton.properties.isDisabled = true
- }
- }
- saveButton.reloadData()
- }
-
- func clearData() {
- watermarkData = KMPDFWatermarkData()
-
- reloadData()
- }
-
- //MARK: - Action
- @objc func leftTopButtonClicked(_ sender: ComponentButton) {
- if sender == leftTopButton {
- var isChanged = false
- if let dict = self.originalDataDict {
- isChanged = KMWatermarkManager.compareIsChangedModel(watermarkData, withDict: dict as NSDictionary)
- }
- if isChanged == true {
- let alert = NSAlert()
- alert.alertStyle = .critical
- alert.messageText = KMLocalizedString("Save template changes?")
- alert.informativeText = KMLocalizedString("Cancel and they will not be saved.")
- alert.addButton(withTitle: KMLocalizedString("Save"))
- alert.addButton(withTitle: KMLocalizedString("Cancel"))
- alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
- if response == NSApplication.ModalResponse.alertFirstButtonReturn {
- self.templateButtonClicked(self.templateButton)
- } else {
- if let dict = self.originalDataDict {
- KMWatermarkManager.defaultManager.setDictToWatermarK(dict: dict as NSDictionary, self.watermarkData)
- let _ = KMWatermarkManager.defaultManager.updateWatermark(watermark: self.watermarkData)
- }
- self.delegate?.watermarkPropertyControllerCancelTemplateEdit?(self)
-
- }
- }
- } else {
- delegate?.watermarkPropertyControllerCancelTemplateEdit?(self)
-
- }
- }
- }
-
- @objc func templateButtonClicked(_ sender: ComponentButton) {
- if editSubType == .edit {
- let _ = KMWatermarkManager.defaultManager.updateWatermark(watermark: watermarkData)
- delegate?.watermarkPropertyControllerSaveTemplateSuccess?(self, self.watermarkData)
- } else {
- if watermarkData.watermarkType == .image, let _ = watermarkData.imagePath {
- watermarkData.text = nil
- watermarkData.watermarkType = .image
- } else {
- watermarkData.watermarkType = .text
- watermarkData.imagePath = nil
- }
- delegate?.watermarkPropertyControllerDidChangetoTemplate?(self)
- }
- }
-
- @objc func checkBoxClicked(_ sender: ComponentCheckBox) {
- if sender == appearanceScaleCheckbox {
- watermarkData.isScale = appearanceScaleCheckbox.properties.checkboxType == .selected ? true : false
- } else if sender == positionTileCheckbox {
- watermarkData.isTilePage = positionTileCheckbox.properties.checkboxType == .selected ? true : false
- }
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
-
- @objc func radioClicked(_ sender: ComponentRadio) {
- if sender == appearanceTopPageRadio {
- watermarkData.isFront = true
- } else if sender == appearanceBottomPageRadio {
- watermarkData.isFront = false
- }
-
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
-
- @objc func saveButtonClicked(_ sender: ComponentButton) {
- let saveWindow: KMWatermarkSaveWindow = KMWatermarkSaveWindow(windowNibName: "KMWatermarkSaveWindow")
- if watermarkData.watermarkType == .image {
- saveWindow.nameValue = watermarkData.imagePath?.lastPathComponent ?? ""
- } else if watermarkData.watermarkType == .text {
- saveWindow.nameValue = watermarkData.text ?? ""
- }
- saveWindow.saveHandler = {[weak self] string in
- guard let weakSelf = self else { return }
-
- DispatchQueue.main.async {
- weakSelf.watermarkData.watermarkName = string ?? ""
- if KMWatermarkManager.defaultManager.addWatermark(watermark: weakSelf.watermarkData) == true {
- weakSelf.delegate?.watermarkPropertyControllerSaveTemplateSuccess?(weakSelf, weakSelf.watermarkData)
- }
- }
- }
- saveWindow.own_beginSheetModal(for: view.window) { string in
-
- }
- }
-
- @objc func chooseURLAction(_ sender: NSView) {
- self.chooseURLAction(sender, nil)
- }
-
- func chooseURLAction(_ sender: NSView, _ filePath: String? = nil) {
-
- let openPanel = NSOpenPanel()
- openPanel.canChooseDirectories = false
- openPanel.canChooseFiles = true
- openPanel.allowsMultipleSelection = false
- openPanel.allowedFileTypes = ["jpg", "jpeg", "png", "pdf"]
-
- openPanel.beginSheetModal(for: self.view.window!) { (result) in
- if result == NSApplication.ModalResponse.OK {
- guard let url = openPanel.url else { return }
- let filePath = url.path
-
- let outFolder = KMWatermarkManager.defaultManager.watermarkImageFolder
- let fileName = filePath.getLastComponentDeleteExtension
-
- if filePath.extension.lowercased() == ".pdf" {
- let pdf = CPDFDocument(url: url)
- guard !pdf!.isEncrypted else { return }
-
- if let image = self.generateThumbnail(for: url) {
-
- if let outFolderPath = outFolder?.stringByAppendingPathComponent(fileName + ".png") {
- try?image.pngData()?.write(to: URL(fileURLWithPath: outFolderPath))
-
- if FileManager.default.fileExists(atPath: outFolderPath) {
- self.watermarkData.imagePath = outFolderPath
- }
- self.delegate?.watermarkPropertyControllerDidUpdate?(self)
-
- self.reloadData()
- }
- }
- } else {
- let image = NSImage(contentsOfFile: url.path)
- if image == nil || NSImage.isDamageImage(image, imagePath: url.path) {
- let alert = NSAlert()
- alert.alertStyle = .critical
- alert.messageText = "The file \"\(url.lastPathComponent)\" could not be opened."
- alert.informativeText = "It may be damaged or use a file format that PDF Reader Pro doesn’t recognize."
- alert.addButton(withTitle: "Cancel")
- alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in
- if response == NSApplication.ModalResponse.alertFirstButtonReturn {
- // Cancel button clicked
- }
- }
- return
- }
- if let resultPath = outFolder?.stringByAppendingPathComponent(fileName + ".png") {
- try?FileManager.default.copyItem(atPath: url.path, toPath: resultPath)
- self.watermarkData.imagePath = resultPath
- }
-
- self.delegate?.watermarkPropertyControllerDidUpdate?(self)
-
- self.reloadData()
- }
- }
- }
- }
-
- func generateThumbnail(for pdfURL: URL) -> NSImage? {
- // 创建PDF文档
- guard let pdfDocument = CGPDFDocument(pdfURL as CFURL),
- let pdfPage = pdfDocument.page(at: 1) else {
- print("打开PDF文件失败")
- return nil
- }
-
- // 获取页面尺寸
- let pageRect = pdfPage.getBoxRect(.mediaBox)
-
- // 创建图形上下文
- let size = NSSize(width: 200, height: 300)
- let bitsPerComponent = 8
- let bytesPerPixel = 4
- let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue
- let context = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: bitsPerComponent, bytesPerRow: 0, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: bitmapInfo)
-
- // 绘制PDF页面
- context?.saveGState()
- context?.translateBy(x: 0, y: size.height)
- context?.scaleBy(x: 1.0, y: -1.0) // 反转坐标系
- context?.scaleBy(x: size.width / pageRect.width, y: size.height / pageRect.height) // 缩放
- context?.drawPDFPage(pdfPage)
- context?.restoreGState()
-
- // 创建NSImage
- if let cgImage = context?.makeImage() {
- return NSImage(cgImage: cgImage, size: NSSize(width: size.width, height: size.height))
- } else {
- return nil
- }
- }
-
- //MARK: - Mouse
- override func mouseDown(with event: NSEvent) {
- super.mouseDown(with: event)
-
- view.window?.makeFirstResponder(nil)
- }
- }
- //MARK: - ComponentTabsDelegate
- extension KMNWatermarkPropertyController: ComponentTabsDelegate {
- func componentTabsDidSelected(_ view: ComponentTabs, _ property: ComponentTabsProperty) {
- if property == textTabProperty {
- if watermarkData.watermarkType != .text {
- delegate?.watermarkPropertyControllerDidRemoveWatermark?(self, .text)
- }
- watermarkData.watermarkType = .text
- } else if property == fileTabProperty {
- if watermarkData.watermarkType != .image {
- delegate?.watermarkPropertyControllerDidRemoveWatermark?(self, .image)
- }
- watermarkData.watermarkType = .image
- }
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
-
- refreshScrollView()
- }
- }
- //MARK: - ComponentTextareaDelegate
- extension KMNWatermarkPropertyController: ComponentTextareaDelegate {
- func componentTextareaTextDidChange(_ view: ComponentTextarea) {
- watermarkData.text = view.properties.text
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
-
- }
-
- func componentTextareaTextDidEndEditing(_ view: ComponentTextarea) {
- watermarkData.text = view.properties.text
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
- }
- //MARK: - ComponentCColorDelegate
- extension KMNWatermarkPropertyController: ComponentCColorDelegate {
- func componentCColorDidChooseColor(_ view: NSView, _ color: NSColor?) {
- if view == fontColorGroup {
- watermarkData.textColor = color ?? NSColor.clear
- }
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
- }
- //MARK: - ComponentSelectDelegate
- extension KMNWatermarkPropertyController: ComponentSelectDelegate {
- func componentSelectDidSelect(view: ComponentSelect?, menuItemProperty: ComponentMenuitemProperty?) {
- if view == fontNameSelect {
- watermarkData.fontName = menuItemProperty?.text ?? "Helvetica"
- watermarkData.fontStyle = nil
- } else if view == fontStyleSelect {
- watermarkData.fontStyle = menuItemProperty?.text
- } else if view == fontSizeSelect {
- if let text = menuItemProperty?.text {
- let result = text.stringByDeleteCharString(" pt")
- watermarkData.fontSize = result.stringToCGFloat()
- }
- } else if view == appearance_OpacitySelect {
- if let text = menuItemProperty?.text {
- let result = text.stringByDeleteCharString("%")
- watermarkData.opacity = result.stringToCGFloat()/100
- }
- } else if view == appearance_RotateSelect {
- if let text = menuItemProperty?.text {
- let result = text.stringByDeleteCharString("°")
- watermarkData.rotation = result.stringToCGFloat()
- }
- } else if view == appearanceScaleSelect {
- if let text = menuItemProperty?.text {
- let result = text.stringByDeleteCharString("%")
- watermarkData.scale = result.stringToCGFloat()/100
- }
- }
-
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
-
- func componentSelectTextDidChange(_ view: ComponentSelect) {
- if view == fontSizeSelect {
- if let string = view.properties.text {
- let size = string.stringToCGFloat()
- watermarkData.fontSize = size
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
- }
- }
-
- func componentSelectTextDidEndEditing(_ view: ComponentSelect) {
- if view == fontSizeSelect {
- if let string = view.properties.text {
- let result = string.stringByDeleteCharString(" pt")
-
- let size = result.stringToCGFloat()
- watermarkData.fontSize = size
-
- }
- } else if view == appearance_OpacitySelect {
- if let text = appearance_OpacitySelect.properties.text {
- let result = text.stringByDeleteCharString("%")
- watermarkData.opacity = result.stringToCGFloat()/100
- }
- } else if view == appearance_RotateSelect {
- if let text = appearance_RotateSelect.properties.text {
- let result = text.stringByDeleteCharString("°")
- watermarkData.rotation = result.stringToCGFloat()
- }
- } else if view == appearanceScaleSelect {
- if let text = appearanceScaleSelect.properties.text {
- let result = text.stringByDeleteCharString("%")
- watermarkData.scale = result.stringToCGFloat()/100
- }
- }
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
-
- }
-
-
-
- }
- //MARK: - ComponentCPositionDelegate
- extension KMNWatermarkPropertyController: ComponentCPositionDelegate {
- func componentCPositionDidChoose(_ view: NSView, _ row: Int, _ column: Int) {
- if view == positionItemView {
- if row == 0 {
- watermarkData.verticalPosition = .bottom
- } else if row == 1 {
- watermarkData.verticalPosition = .center
- } else if row == 2 {
- watermarkData.verticalPosition = .top
- }
-
- if column == 0 {
- watermarkData.horizontalPosition = .left
- } else if column == 1 {
- watermarkData.horizontalPosition = .center
- } else if column == 2 {
- watermarkData.horizontalPosition = .right
- }
- }
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
- }
- //MARK: - ComponentInputNumberDelegate
- extension KMNWatermarkPropertyController: ComponentInputNumberDelegate {
- func componentInputNumberDidValueChanged(inputNumber: ComponentInputNumber?) {
- if inputNumber == positionXInput {
- if let text = inputNumber?.properties.text {
- watermarkData.tx = text.stringToCGFloat()
- }
- } else if inputNumber == positionYInput {
- if let text = inputNumber?.properties.text {
- watermarkData.ty = text.stringToCGFloat()
- }
- } else if inputNumber == positionTileHoriInput {
- if let text = inputNumber?.properties.text {
- watermarkData.horizontalSpacing = text.stringToCGFloat()
- }
- } else if inputNumber == positionTileVertInput {
- if let text = inputNumber?.properties.text {
- watermarkData.verticalSpacing = text.stringToCGFloat()
- }
- }
- reloadData()
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
- }
- //MARK: - ComponentInputDelegate
- extension KMNWatermarkPropertyController: ComponentInputDelegate {
- func componentInputDidCoverButtonClicked(inputView: ComponentInput) {
- if inputView.properties.text.count > 0 && inputView.properties.creatable == false {
- self.chooseURLAction(inputView, inputView.properties.text)
- }
- }
- }
|