// // KMPDFEditToolbar.swift // PDF Reader Pro // // Created by tangchao on 2023/5/4. // import Cocoa enum KMPageEditType: Int { case none = 0 case pageRange = 1 case leftRotate case rightRotate case insert case extract case replace case split case reverse case copy case delete case zoomOut case zoomIn case paste = 100 // static let none: KMPageEditType = KMPageEditType(rawValue: 0)! // static let paste: KMPageEditType = KMPageEditType(rawValue: 100)! static var insert_files: Int { get { return self.insert.rawValue + 1000 } } static var insert_blank_page: Int { get { return self.insert.rawValue + 1001 } } static var insert_custom_page: Int { get { return self.insert.rawValue + 1002 } } static var extract_selected_pages: Int { get { return self.extract.rawValue + 2000 } } static var split_selected_pages: Int { get { return self.split.rawValue + 3000 } } } class KMPDFEditToolbar: NSView { private var toolBar_ = KMToolbarView.init(identifier: "KMPageEditIdentifier") var toolBar: KMToolbarView { get { return self.toolBar_ } } private var zoomOutButton_: NSButton? private var zoomInButton_: NSButton? open var zoomOutButton: NSButton? { get { return self.zoomOutButton_ } } open var zoomInButton: NSButton? { get { return self.zoomInButton_ } } private var pageRangeView_: KMDesignSelect? open var pageRangeView: KMDesignSelect? { get { return self.pageRangeView_ } } private var pageRangeViewItems = [KMTools.pageRangeTypeString(pageRange: .all), KMTools.pageRangeTypeString(pageRange: .odd), KMTools.pageRangeTypeString(pageRange: .even), KMTools.pageRangeTypeString(pageRange: .horizontal), KMTools.pageRangeTypeString(pageRange: .vertical), KMTools.pageRangeTypeString(pageRange: .custom)] var itemClick: KMItemClickBlock? var pageRangeitemClick: ((KMPageRange)->Void)? var pageRangeValueDidChange: KMValueDidChangeBlock? lazy var insertItemStrings: [String] = { return [NSLocalizedString("Blank Page", comment: ""), NSLocalizedString("Blank Page - Custom...", comment: ""), NSLocalizedString("From PDF", comment: "")] }() private weak var popover: NSPopover? override init(frame frameRect: NSRect) { super.init(frame: frameRect) self.initDefaultValue() self.initSubViews() } required init?(coder: NSCoder) { super.init(coder: coder) self.initDefaultValue() self.initSubViews() } public func initDefaultValue() { } public func initSubViews() { self.addSubview(self.toolBar) self.toolBar.frame = self.bounds self.toolBar.autoresizingMask = [.width, .height] self.toolBar.delegate = self // let rightItemView = self.rightItemView // self.addSubview(rightItemView) // rightItemView.frame = NSMakeRect(NSWidth(self.frame)-80, 0, 80, NSHeight(self.frame)) // rightItemView.autoresizingMask = [.minXMargin, .height] } // MARK: - Publick Methods public func setPageRangeString(_ string: String) { self.pageRangeView?.stringValue = string self.pageRangeView?.editable = true } public func getItem(for itemId: String) -> KMToolbarItemView? { return self.toolBar.itemForItemIdentifier(itemId) } public func selectItem(for itemId: String) { self.getItem(for: itemId)?.isSelected = true } public func unSelectItem(for itemId: String) { self.getItem(for: itemId)?.isSelected = false } // MARK: - Actions @objc private func zoomOutButtonAction() { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.zoomOut.rawValue) } @objc private func zoomInButtonAction() { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.zoomIn.rawValue) } // MARK: toolBar 菜单事件 @objc func pageRangeMenuAction(sender: KMToolbarClickButton) { if let subMenu = (sender.clickObject as? KMToolbarItemView)?.menuFormRepresentation?.submenu { subMenu.popUp(positioning: nil, at: sender.frame.origin, in: sender.superview) } } @objc private func _pageRangeAction(sender: NSMenuItem) { guard let type = KMPageRange(rawValue: sender.tag) else { return } guard let callback = self.pageRangeitemClick else { return } callback(type) } @objc func leftRotateMenuAction(sender: KMToolbarClickButton?) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.leftRotate.rawValue) } @objc func rightRotateMenuAction(sender: KMToolbarClickButton?) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.rightRotate.rawValue) } @objc func insertMenuAction(sender: KMToolbarClickButton) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.insert.rawValue) if let _popover = self.popover, _popover.isShown { self.popover?.close() self.popover = nil return } let vc: KMHomePopViewController = KMHomePopViewController().initWithPopViewDataArr(self.insertItemStrings) let popover: NSPopover = NSPopover.init() self.popover = popover popover.contentViewController = vc popover.animates = true popover.behavior = .semitransient popover.setValue(true, forKey: "shouldHideAnchor") popover.show(relativeTo: CGRect(x: sender.bounds.origin.x, y: 10, width: sender.bounds.size.width, height: sender.bounds.size.height), of: sender, preferredEdge: .maxY) vc.downCallback = { [weak self] downEntered, count in self?.popover?.close() self?.popover = nil if (!downEntered) { return } guard let index = self?.insertItemStrings.firstIndex(of: count) else { return } if (index == 0) { self?.item_insertBlankPage(sender: nil) } else if (index == 1) { self?.item_insertCustomPage(sender: nil) } else if (index == 2) { self?.item_insertFile(sender: nil) } } } @objc func extractMenuAction(sender: KMToolbarClickButton?) { // guard let callback = self.itemClick else { // return // } // callback(self, KMPageEditType.insert.rawValue) if let _popover = self.popover, _popover.isShown { self.popover?.close() self.popover = nil return } let array = [NSLocalizedString("Extract selected pages", comment: ""), NSLocalizedString("Extract", comment: "")] let vc: KMHomePopViewController = KMHomePopViewController().initWithPopViewDataArr(array) let popover: NSPopover = NSPopover.init() self.popover = popover popover.contentViewController = vc popover.animates = true popover.behavior = .semitransient popover.setValue(true, forKey: "shouldHideAnchor") if let data = sender { popover.show(relativeTo: CGRect(x: sender?.bounds.origin.x ?? 0, y: 10, width: sender?.bounds.size.width ?? 0, height: sender?.bounds.size.height ?? 0), of: data, preferredEdge: .maxY) } vc.downCallback = { [weak self] downEntered, count in self?.popover?.close() self?.popover = nil if (!downEntered) { return } guard let index = array.firstIndex(of: count) else { return } if (index == 0) { guard let callback = self?.itemClick else { return } callback(self, KMPageEditType.extract_selected_pages) } else if (index == 1) { guard let callback = self?.itemClick else { return } callback(self, KMPageEditType.extract.rawValue) } } } @objc private func _extractMenuItemAction(_ sender: NSMenuItem) { if (sender.tag == 1) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.extract_selected_pages) } else if (sender.tag == 2) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.extract.rawValue) } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Extract"]) } @objc func replaceMenuAction(sender: KMToolbarClickButton?) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.replace.rawValue) } @objc func splitMenuAction(sender: KMToolbarClickButton) { if let subMenu = (sender.clickObject as? KMToolbarItemView)?.menuFormRepresentation?.submenu { subMenu.popUp(positioning: nil, at: sender.frame.origin, in: sender.superview) } } @objc func reverseMenuAction(sender: KMToolbarClickButton) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.reverse.rawValue) } @objc func copyMenuAction(sender: KMToolbarClickButton) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.copy.rawValue) } @objc func pasteMenuAction(sender: KMToolbarClickButton) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.paste.rawValue) } @objc func deleteMenuAction(sender: KMToolbarClickButton) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.delete.rawValue) } @objc func item_insertFile(sender: NSMenuItem?) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.insert_files) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Insert"]) } @objc func item_insertBlankPage(sender: NSMenuItem?) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.insert_blank_page) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Insert"]) } @objc func item_insertCustomPage(sender: NSMenuItem?) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.insert_custom_page) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Insert"]) } @objc private func _splitAction(sender: NSMenuItem) { if (sender.tag == 1) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.split.rawValue) return } guard let callback = self.itemClick else { return } callback(self, KMPageEditType.split_selected_pages) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Split"]) } private lazy var rightItemView: NSView = { let view = NSView() let size: CGFloat = 28 let y: CGFloat = 6 let zoomInButton = NSButton() view.addSubview(zoomInButton) zoomInButton.frame = NSMakeRect(0, y, size, size) zoomInButton.isBordered = false zoomInButton.image = NSImage(named: "KMImageNamePageEditZoomIn") zoomInButton.target = self zoomInButton.action = #selector(zoomInButtonAction) self.zoomInButton_ = zoomInButton let zoomOutButton = NSButton() view.addSubview(zoomOutButton) zoomOutButton.frame = NSMakeRect(size+7, y, size, size) zoomOutButton.isBordered = false zoomOutButton.image = NSImage(named: "KMImageNamePageEditZoomOut") zoomOutButton.target = self zoomOutButton.action = #selector(zoomOutButtonAction) self.zoomOutButton_ = zoomOutButton return view }() } // MARK: - KMNewToolbarDelegate extension KMPDFEditToolbar: KMToolbarViewDelegate { func toolbarDefaultItemIdentifiers(_ toolbar: KMToolbarView) -> [String] { return [KMToolbarPageEditPageRangeItemIdentifier, // KMToolbarPageEditLeftRotateItemIdentifier, // KMToolbarPageEditRightRotateItemIdentifier, KMToolbarDividerItemIdentifier, KMToolbarPageEditInsetItemIdentifier, KMToolbarPageEditReplaceItemIdentifier, KMToolbarPageEditExtractItemIdentifier, KMToolbarPageEditSplitItemIdentifier, KMToolbarPageEditRotateItemIdentifier, KMToolbarPageEditReverseItemIdentifier, KMToolbarPageEditCopyItemIdentifier, KMToolbarPageEditPasteItemIdentifier, KMToolbarPageEditDeleteItemIdentifier] } func toolbar(_ toolbar: KMToolbarView, itemFor identifier: String) -> KMToolbarItemView { let item: KMToolbarItemView? = KMToolbarCustomItemView(itemIdentifier: identifier) if (identifier == KMToolbarPageEditPageRangeItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageRange) item?.target = self item?.btnTag = KMPageEditType.pageRange.rawValue // item?.toolTip = NSLocalizedString("pageRange", comment: "") item?.titleName = NSLocalizedString("Page Range", comment: "") item?.boxImagePosition = .imageExpandLeft // item?.btnAction = #selector(pageRangeMenuAction) item?.needExpandAction = true // let view = NSView() // item?.addSubview(view) // view.frame = item!.bounds // view.autoresizingMask = [.width,.height] // view.wantsLayer = true // view.layer?.backgroundColor = NSColor.km_init(hex: "#F7F8FA").cgColor // let comBoxView = KMDesignSelect(withType: .Combox) // view.addSubview(comBoxView.view) // comBoxView.view.frame = NSMakeRect(0, 0.5, NSWidth(view.frame), 21) // comBoxView.view.autoresizingMask = [.width] // comBoxView.removeAllItems() // comBoxView.addItems(withObjectValues: self.pageRangeViewItems) // comBoxView.selectItem(at: 0) // comBoxView.placeholderString = NSLocalizedString("eg .1,3-5,10", comment: "") // comBoxView.editable = false // comBoxView.delete = self // self.pageRangeView_ = comBoxView let menuItem = NSMenuItem.init(title: NSLocalizedString("Page Range", comment: ""), action: #selector(pageRangeMenuAction), target: self) let subMenu = NSMenu() subMenu.addItem(title: NSLocalizedString("Odd Pages Only", comment: ""), action: #selector(_pageRangeAction), target: self, tag: KMPageRange.odd.rawValue) subMenu.addItem(title: NSLocalizedString("Even Pages Only", comment: ""), action: #selector(_pageRangeAction), target: self, tag: KMPageRange.even.rawValue) subMenu.addItem(title: NSLocalizedString("Portrait pages", comment: ""), action: #selector(_pageRangeAction), target: self, tag: KMPageRange.vertical.rawValue) subMenu.addItem(title: NSLocalizedString("Landscape pages", comment: ""), action: #selector(_pageRangeAction), target: self, tag: KMPageRange.horizontal.rawValue) subMenu.addItem(title: NSLocalizedString("All Pages", comment: ""), action: #selector(_pageRangeAction), target: self, tag: KMPageRange.all.rawValue) subMenu.addItem(.separator()) subMenu.addItem(title: NSLocalizedString("Customize", comment: ""), action: #selector(_pageRangeAction), target: self, tag: KMPageRange.custom.rawValue) menuItem.submenu = subMenu item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditRotateItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageRotate) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPageRotate) item?.target = self item?.btnTag = KMPageEditType.rightRotate.rawValue item?.toolTip = NSLocalizedString("Rotate", comment: "") item?.titleName = NSLocalizedString("Rotate", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(rightRotateMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Rotate", comment: ""), action: #selector(rightRotateMenuAction), target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditLeftRotateItemIdentifier) { item?.image = NSImage(named: "KMImageNameMainToolPageLeftRotate") item?.alternateImage = NSImage(named: "KMImageNameMainToolPageLeftRotate") item?.target = self item?.btnTag = KMPageEditType.leftRotate.rawValue item?.toolTip = NSLocalizedString("Rotate Left", comment: "") item?.titleName = NSLocalizedString("", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(leftRotateMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Rotate Left", comment: ""), action: #selector(leftRotateMenuAction), target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditRightRotateItemIdentifier) { item?.image = NSImage(named: "KMImageNameMainToolPageRightRotate") item?.alternateImage = NSImage(named: "KMImageNameMainToolPageRightRotate") item?.target = self item?.btnTag = KMPageEditType.rightRotate.rawValue item?.toolTip = NSLocalizedString("Rotate Right", comment: "") item?.titleName = NSLocalizedString("", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(rightRotateMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Rotate Right", comment: ""), action: #selector(rightRotateMenuAction), target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditInsetItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageInsert) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPageInsert) item?.target = self item?.btnTag = KMPageEditType.insert.rawValue // item?.toolTip = NSLocalizedString("Inserting pages into an existing PDF", comment: "") item?.titleName = NSLocalizedString("Insert", comment: "") item?.boxImagePosition = .imageExpandLeft // item?.btnAction = #selector(insertMenuAction) item?.needExpandAction = true let menuItem = NSMenuItem.init(title: NSLocalizedString("Insert", comment: ""), action: nil, target: self) let subMenu = NSMenu() menuItem.submenu = subMenu _ = subMenu.addItem(title: self.insertItemStrings[0], action: #selector(item_insertBlankPage) , target: self) _ = subMenu.addItem(title: self.insertItemStrings[1], action: #selector(item_insertCustomPage) , target: self) _ = subMenu.addItem(title: self.insertItemStrings[2], action: #selector(item_insertFile) , target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditExtractItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageExtract) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPageExtract) item?.target = self item?.btnTag = KMPageEditType.extract.rawValue // item?.toolTip = NSLocalizedString("Exctract selected pages", comment: "") item?.titleName = NSLocalizedString("Extract", comment: "") item?.boxImagePosition = .imageExpandLeft // item?.btnAction = #selector(extractMenuAction) item?.needExpandAction = true let menuItem = NSMenuItem.init(title: NSLocalizedString("Extract", comment: ""), action: nil, target: self) let subMenu = NSMenu() menuItem.submenu = subMenu subMenu.addItem(title: NSLocalizedString("Extract selected pages", comment: ""), action: #selector(_extractMenuItemAction) , target: self, tag: 1) subMenu.addItem(title: NSLocalizedString("Extract", comment: ""), action: #selector(_extractMenuItemAction) , target: self, tag: 2) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditReplaceItemIdentifier) { item?.image = NSImage(named: KMImageNameToolbarReplace) item?.alternateImage = NSImage(named: KMImageNameToolbarReplace) item?.target = self item?.btnTag = KMPageEditType.replace.rawValue item?.toolTip = NSLocalizedString("Replace", comment: "") item?.titleName = NSLocalizedString("Replace", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(replaceMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Replace", comment: ""), action: #selector(replaceMenuAction), target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditSplitItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageSplit) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPageSplit) item?.target = self item?.btnTag = KMPageEditType.split.rawValue // item?.toolTip = NSLocalizedString("Split and save selected PDF pages as a new separate document", comment: "") item?.titleName = NSLocalizedString("Split", comment: "") item?.boxImagePosition = .imageExpandLeft item?.needExpandAction = true // item?.btnAction = #selector(splitMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Split", comment: ""), action: nil, target: self) let subMenu = NSMenu() subMenu.addItem(title: NSLocalizedString("Split selected pages", comment: ""), action: #selector(_splitAction), target: self, tag: 0) subMenu.addItem(title: NSLocalizedString("Split", comment: ""), action: #selector(_splitAction), target: self, tag: 1) menuItem.submenu = subMenu item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditReverseItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageReverse) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPageReverse) item?.target = self item?.btnTag = KMPageEditType.reverse.rawValue item?.toolTip = NSLocalizedString("Reverse", comment: "") item?.titleName = NSLocalizedString("Reverse", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(reverseMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Reverse", comment: ""), action: #selector(reverseMenuAction), target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditCopyItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageCopy) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPageCopy) item?.target = self item?.btnTag = KMPageEditType.delete.rawValue item?.toolTip = NSLocalizedString("Copy", comment: "") item?.titleName = NSLocalizedString("Copy", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(copyMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Copy", comment: ""), action: #selector(copyMenuAction), target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditPasteItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPagePaste) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPagePaste) item?.target = self item?.btnTag = KMPageEditType.delete.rawValue item?.toolTip = NSLocalizedString("Paste", comment: "") item?.titleName = NSLocalizedString("Paste", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(pasteMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Paste", comment: ""), action: #selector(pasteMenuAction), target: self) item?.menuFormRepresentation = menuItem } else if (identifier == KMToolbarPageEditDeleteItemIdentifier) { item?.image = NSImage(named: KMImageNameUXIconSubtoolbarPageDelete) item?.alternateImage = NSImage(named: KMImageNameUXIconSubtoolbarPageDelete) item?.target = self item?.btnTag = KMPageEditType.delete.rawValue item?.toolTip = NSLocalizedString("Delete", comment: "") item?.titleName = NSLocalizedString("Delete", comment: "") item?.boxImagePosition = .imageLeft item?.btnAction = #selector(deleteMenuAction) let menuItem = NSMenuItem.init(title: NSLocalizedString("Delete", comment: ""), action: #selector(deleteMenuAction), target: self) item?.menuFormRepresentation = menuItem } return item! } } // MARK: - KMSelectPopButtonDelegate extension KMPDFEditToolbar: KMSelectPopButtonDelegate { func km_comboBoxSelectionDidChange(_ obj: KMDesignSelect) { guard let callback = self.itemClick else { return } callback(self, KMPageEditType.pageRange.rawValue) } func km_controlTextDidChange(_ obj: KMDesignSelect) { } func km_controlTextDidEndEditing(_ obj: KMDesignSelect) { guard let callback = self.pageRangeValueDidChange else { return } callback(self.pageRangeView?.stringValue, nil) } }