1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024 |
- //
- // 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: KMWatermarkModel)
-
- //取消修改模板信息
- @objc optional func watermarkPropertyControllerCancelTemplateEdit(_ controller: KMNWatermarkPropertyController)
-
- }
- class KMNWatermarkPropertyController: KMNBaseViewController {
-
- @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!
- @IBOutlet var appearanceScaleCheckboxWidthConst: NSLayoutConstraint!
- @IBOutlet var appearanceTopPageRadioWidthConst: NSLayoutConstraint!
- @IBOutlet var BottomPageRadioWidthConst: 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!
- @IBOutlet var positionTileCheckboxConst: NSLayoutConstraint!
-
- //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 chooseFileURL: URL?
-
- var watermarkData: KMWatermarkModel = KMWatermarkManager.defaultManager.defaultWatermarkData
-
- public var editSubType: KMPDFEditSubModeType = .add
- public var isInBatchMode: Bool = false
-
- var originalDataDict: Dictionary<String, Any>?
-
- weak open var delegate: KMNWatermarkPropertyControllerDelegate?
-
- /**
- 1、新增模板:新增完成后,重置缓存数据
- 2、修改模板:
- */
- //MARK: - func
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do view setup here.
-
- infoScrollView.documentView = infoContendView
- infoScrollView.scrollerStyle = .overlay
- infoScrollView.layout()
-
- setupProperty()
-
- reloadData()
-
- refreshScrollView()
- }
-
- override func updateUILanguage() {
- super.updateUILanguage()
-
- configUI()
- }
-
- override func updateUIThemeColor() {
- super.updateUIThemeColor()
-
- configUI()
- }
-
- func setupProperty() {
-
- 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: KMLocalizedString("Select 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_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"), checkboxType: .normal)
- appearanceScaleCheckboxWidthConst.constant = appearanceScaleCheckbox.properties.propertyInfo.viewWidth
-
- 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("Appear on top of page"), checkboxType: .normal)
- appearanceTopPageRadioWidthConst.constant = appearanceTopPageRadio.properties.propertyInfo.viewWidth
-
- appearanceTopPageRadio.setTarget(self, action: #selector(radioClicked(_:)))
-
- appearanceBottomPageRadio.properties = ComponentCheckBoxProperty(size: .s, text: KMLocalizedString("Appear behind page"), checkboxType: .normal)
- BottomPageRadioWidthConst.constant = appearanceBottomPageRadio.properties.propertyInfo.viewWidth
-
- appearanceBottomPageRadio.setTarget(self, action: #selector(radioClicked(_:)))
-
-
- //Position
- 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)
- positionTileCheckboxConst.constant = positionTileCheckbox.properties.propertyInfo.viewWidth
-
- 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
-
- 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 configUI() {
- contendView.wantsLayer = true
- contendView.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle").cgColor
-
- textTabProperty.title = KMLocalizedString("Text")
- fileTabProperty.title = KMLocalizedString("File")
- typeTabs.refreshItems()
- titleLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- titleLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-bold")
-
- text_textareaView.properties.placeholderString = KMLocalizedString("Please enter...")
- text_textareaView.reloadData()
-
- fileInputView.properties.placeholder = KMLocalizedString("Select File")
- fileInputView.reloadData()
-
- appearanceScaleCheckbox.properties.text = KMLocalizedString("Scale")
- appearanceScaleCheckbox.reloadData()
-
- //Appearance
- appearanceLabel.stringValue = KMLocalizedString("Appearance")
- appearanceLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- appearanceLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
-
- appearanceTopPageRadio.properties.text = KMLocalizedString("Appear on top of page")
- appearanceTopPageRadio.properties = appearanceTopPageRadio.properties
- appearanceTopPageRadioWidthConst.constant = appearanceTopPageRadio.properties.propertyInfo.viewWidth
-
- appearanceBottomPageRadio.properties.text = KMLocalizedString("Appear behind page")
- appearanceBottomPageRadio.properties = appearanceBottomPageRadio.properties
- BottomPageRadioWidthConst.constant = appearanceBottomPageRadio.properties.propertyInfo.viewWidth
- //Position
- positionLabel.stringValue = KMLocalizedString("Position") + " (mm) "
- positionLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- positionLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
-
- positionTileCheckbox.properties.text = KMLocalizedString("Tile")
- positionTileCheckbox.properties = positionTileCheckbox.properties
- positionTileCheckboxConst.constant = positionTileCheckbox.properties.propertyInfo.viewWidth
- //Save
- saveTemplateBGView.wantsLayer = true
- saveTemplateBGView.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle").cgColor
-
- saveButton.properties.buttonText = KMLocalizedString("Save as Template")
- saveButton.reloadData()
- }
-
- func refreshScrollView() {
- infoScrollView.contentViewSize = CGSizeMake(264, 672)
- if watermarkData.watermarkType == .text {
- infoScrollView.contentViewSize = CGSizeMake(264, 672)
- infoScrollView.layout()
- } else if watermarkData.watermarkType == .image {
- infoScrollView.contentViewSize = CGSizeMake(264, 520)
- infoScrollView.layout()
- }
- infoScrollView.scrollToTop()
- }
-
- public func scrollToTop() {
- self.infoScrollView.scrollToTop()
- }
-
- public func beginEditing() {
- if watermarkData.watermarkType == .text {
- self.text_textareaView.beginEditing()
- }
- }
-
- func reloadData() {
- titleLabel.stringValue = KMLocalizedString("Add Watermark")
- leftTopButton.isHidden = true
- saveTemplateBGView.isHidden = false
- templateButton.properties.isDisabled = 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("Appearance")
- leftTopButton.isHidden = false
- saveTemplateBGView.isHidden = true
- templateButton.properties.icon = NSImage(named: "edit_save")
- var isChanged = false
- if let dict = self.originalDataDict {
- isChanged = KMWatermarkManager.compareIsChangedModel(watermarkData, withDict: dict as NSDictionary)
- }
- if isChanged {
- templateButton.properties.isDisabled = false
- } else {
- templateButton.properties.isDisabled = true
- }
- }
- templateButton.reloadData()
-
- if self.isInBatchMode || editSubType == .edit {
- 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()
-
- var row = 0
- var column = 0
- if watermarkData.verticalPosition == .bottom {
- row = 0
- } else if watermarkData.verticalPosition == .center {
- row = 1
- } else if watermarkData.verticalPosition == .top {
- row = 2
- }
-
- if watermarkData.horizontalPosition == .left {
- column = 0
- } else if watermarkData.horizontalPosition == .center {
- column = 1
- } else if watermarkData.horizontalPosition == .right {
- column = 2
- }
- positionItemView.properties.selRow = row
- positionItemView.properties.selColumn = column
- positionItemView.reloadData()
-
- }
-
- func clearData() {
- KMWatermarkManager.defaultManager.defaultWatermarkData = KMWatermarkModel.defaultWDData()
-
- watermarkData = KMWatermarkManager.defaultManager.defaultWatermarkData
-
- reloadData()
- }
-
- func isOriginalDataDictChanged() -> Bool {
- var isChanged = false
- if let dict = self.originalDataDict {
- isChanged = KMWatermarkManager.compareIsChangedModel(watermarkData, withDict: dict as NSDictionary)
- }
- return isChanged
- }
-
- func showSaveEditChangeAlert(completion: @escaping (NSApplication.ModalResponse) -> Void) {
- let alert = NSAlert()
- alert.alertStyle = .critical
- alert.messageText = KMLocalizedString("Save template changes?")
- alert.informativeText = KMLocalizedString("Do you want to apply the changes to the template? If not, the changes will be lost.")
- alert.addButton(withTitle: KMLocalizedString("Save"))
- alert.addButton(withTitle: KMLocalizedString("Cancel"))
- if let window = self.view.window {
- alert.beginSheetModal(for: window) { response in
- completion(response)
- }
- }
- }
-
- func cancelDataEdit() {
- 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)
-
- }
-
- func saveDataEdit() {
- self.templateButtonClicked(self.templateButton)
- }
-
- //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 {
- self.showSaveEditChangeAlert { response in
- if response == NSApplication.ModalResponse.alertFirstButtonReturn {
- //OK
- self.saveDataEdit()
- } else {
- //Cancel
- self.cancelDataEdit()
- }
- }
- } 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)
-
- weakSelf.clearData()
- }
- }
- }
- saveWindow.own_beginSheetModal(for: view.window) { string in
-
- }
- saveWindow.titleLabel.stringValue = KMLocalizedString("Add Watermark")
- }
-
- @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"]
- if let path = filePath {
- openPanel.directoryURL = NSURL.fileURL(withPath: path)
- }
- openPanel.beginSheetModal(for: self.view.window!) { (result) in
- if result == NSApplication.ModalResponse.OK {
- guard let url = openPanel.url else { return }
-
- self.chooseFileURL = url
-
- 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)
- }
-
- func componentCColorGroupColorsUpdates(_ view: NSView, _ colors: [NSColor]) {
- KMAnnotationPropertiesColorManager.manager.updateDefaultColors(colors, forKey: KM_Watermark_default_ColorsKey)
- }
-
- }
- //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 {
- var size = string.stringToCGFloat()
- size = min(size, 288)
- watermarkData.fontSize = size
-
- delegate?.watermarkPropertyControllerDidUpdate?(self)
- }
- }
- }
-
- func componentSelectTextDidEndEditing(_ view: ComponentSelect) {
- if view == fontSizeSelect {
- if let string = view.properties.text {
- let result = string.stringByDeleteCharString(" pt")
-
- var size = result.stringToCGFloat()
- size = min(size, 288)
- 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 let fileURL = self.chooseFileURL, inputView.properties.creatable == false {
- self.chooseURLAction(inputView, fileURL.path)
- }
- }
-
- }
|