12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013 |
- //
- // 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() {
- 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)
- 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
- 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)
- 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
-
-
- //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 configUI() {
- 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")
-
- //Appearance
- appearanceLabel.stringValue = KMLocalizedString("Appearance")
- appearanceLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- appearanceLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
-
- //Position
- positionLabel.stringValue = KMLocalizedString("Position (mm)")
- positionLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- positionLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
-
- //Save
- saveTemplateBGView.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle").cgColor
-
- }
-
- 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("Edit Template")
- 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("Cancel and they will not be saved.")
- 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)
- }
- }
-
- }
|