// // KMToolbarController.swift // PDF Master // // Created by wanjun on 2022/12/29. // import Cocoa extension CAnnotationType { func isAdvanced() -> Bool { if (self == .link || self == .stamp || self == .signSignature) { return true } if (self == .signText || self == .signTure || self == .signFalse || self == .signCircle || self == .signLine || self == .signDot || self == .signDate) { return true } if (self == .addText || self == .addImage) { return true } return false } } @objc protocol KMToolbarControllerDelegate { @objc optional func toolbarController(_ viewController: KMToolbarController, heightOffsetChange heightOffset: Float) @objc optional func changeAnnotationModeAction(item:KMToolbarClickButton) @objc optional func showPDFLayoutModeAction(show:Bool) @objc optional func clickChildTool(type: KMToolbarType, index: Int) @objc optional func changePDFViewZoomModelAction(selectedTag:Int) @objc optional func changePDFViewZoomInAction() @objc optional func changePDFViewZoomOutAction() @objc optional func changePDFViewGotoNextPageAction() @objc optional func changePDFViewGoToPreviousPageAction() @objc optional func changePDFViewGotoBackAction() @objc optional func changePDFViewGoToForwardAction() @objc optional func showPDFViewPrintViewController() @objc optional func aiTranslationPDFFileAction() @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, zoomModel selectedTag:Int) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, zoomSting : String) @objc optional func mainToolDidClicked(_ toolController: KMToolbarController, _ beforeType: KMToolbarViewType, _ type: KMToolbarViewType, _ item: KMToolBoxItem, _ pages: [Int]) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, shareAction toolbarItem: KMToolBoxItem) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, shareDocument item:NSMenuItem) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, shareFlatten item:NSMenuItem) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, shareOriginalPDF item:NSMenuItem) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, scanOCRModel selectedTag:Int) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, rightPanel toolbarItem: KMToolBoxItem) @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, leftPanel toolbarItem: KMToolBoxItem) } class KMToolbarController: NSViewController { @IBOutlet weak var mainToolBarBox: NSBox! @IBOutlet weak var childToolBarBox: NSBox! @IBOutlet weak var secondaryToolBarBox: NSBox! @IBOutlet weak var mainToolBarHeight: NSLayoutConstraint! @IBOutlet weak var childToolBarHeight: NSLayoutConstraint! @IBOutlet weak var secondaryToolBarHeight: NSLayoutConstraint! @IBOutlet weak var bottomOffset: NSLayoutConstraint! var mainToolBarView: KMToolbarViewController? var childToolBarView: KMToolbarViewController? var _toolbarType : KMToolbarViewType = KMToolbarViewType.None var mainViewController: KMMainViewController? open weak var delegate: KMToolbarControllerDelegate? var toolbarItems : [NSToolbarItem.Identifier : Any] = [:] var listView : CPDFListView? var lastItemBox : KMToolBoxItem = KMToolBoxItem() var lastChildItemBox : KMToolBoxItem = KMToolBoxItem() var popover: NSPopover? // 是否显示所有注释 private var _isShowAllAnnotations = true // 是否显示所有注释 var isShowAllAnnotations: Bool { get { return _isShowAllAnnotations } set { _isShowAllAnnotations = newValue self.childToolBarView?.isShowAllAnnotations = newValue self.findChildItem(KMToolbarShowToolbarItemIdentifier)?.isSelected = !newValue } } private var _ignoreCurrentAnnotationTypeChange = false var ignoreCurrentAnnotationTypeChange: Bool { get { return self._ignoreCurrentAnnotationTypeChange } set { self._ignoreCurrentAnnotationTypeChange = newValue self.childToolBarView?.ignoreCurrentAnnotationTypeChange = self.ignoreCurrentAnnotationTypeChange // 忽略后重置 这个属性是基于单次添加,所以使用后会重置 // self._ignoreCurrentAnnotationTypeChange = false } } override func viewDidLoad() { super.viewDidLoad() // Do view setup here. updateViewColor() mainToolBarView = KMToolbarViewController.init() mainToolBarView?.view.wantsLayer = true mainToolBarView?.view.layer?.backgroundColor = NSColor.km_init(hex: "#F7F8FA").cgColor mainToolBarBox.contentView = mainToolBarView?.view mainToolBarView?.view.frame = mainToolBarBox.frame mainToolBarView?.delegate = self mainToolBarView?.view.autoresizingMask = [.width, .height] mainToolBarView?.pdfView = self.listView! childToolBarView = KMToolbarViewController.init() childToolBarView?.view.wantsLayer = true childToolBarView?.view.layer?.backgroundColor = NSColor.km_init(hex: "#F7F8FA").cgColor childToolBarBox.contentView = childToolBarView?.view childToolBarView?.view.frame = childToolBarBox.frame childToolBarView?.delegate = self childToolBarView?.view.autoresizingMask = [.width, .height] childToolBarView?.pdfView = self.listView! toolbarType = .None mainToolBarView?.toolbarType = .Main mainToolBarView?.reloadateToolbar() addObserverForAppearanceChange() NotificationCenter.default.addObserver(self, selector: #selector(selectedShapAnnotationChangeNotification(_:)), name: NSNotification.Name.init(rawValue: "KMSelectedShapAnnotationChangeNotification"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(PDFChangedNotification(_:)), name: NSNotification.Name.init(rawValue: "PDFChangedNotification"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(PDFTextEditPDFChangedNotification(_:)), name: NSNotification.Name.init(rawValue: "KMPDFTextEditPDFChangedNotification"), object: nil) } // MARK: func updateViewColor() -> Void { } // MARK: Setter&Getter var toolbarType: KMToolbarViewType { set { if newValue == _toolbarType { if newValue == .Move || newValue == .Magnify || newValue == .Select || newValue == .SelectZoom { _toolbarType = .Annatiton } else { _toolbarType = .None } } else { _toolbarType = newValue } secondaryToolBarBox.isHidden = true secondaryToolBarHeight.constant = 51 if _toolbarType == .None { bottomOffset.constant = 0 childToolBarBox.isHidden = true self.delegate?.toolbarController?(self, heightOffsetChange: 40) } else if _toolbarType == .Page || _toolbarType == .LeftPanel { bottomOffset.constant = 0 childToolBarBox.isHidden = true self.delegate?.toolbarController?(self, heightOffsetChange: 40) } else { bottomOffset.constant = 41 childToolBarBox.isHidden = false self.delegate?.toolbarController?(self, heightOffsetChange: 81) } childToolBarView?.toolbarType = _toolbarType childToolBarView?.reloadateToolbar() } get { return _toolbarType } } // MARK: Dark&Light func addObserverForAppearanceChange() -> Void { } // MARK: - // MARK: Public Methods // 取消选中 [只是取消选中状态,不会执行具体的方法] public func cancelSelected(_ identifier: String) { if (isMainToolItem(identifier)) { self.findMainItem(identifier)?.isSelected = false return } self.findChildItem(identifier)?.isSelected = false } public func clickItem(_ identifier: String) { self.selectItem(identifier) } public func selectItem(_ identifier: String) { if (isMainToolItem(identifier)) { self.selectMainItem(identifier) return } if let parentItem = self.findItem(parentIdentifier(identifier)), parentItem.isSelected { if (self.trySelectChildItem(identifier)) { // 尝试去选子工具栏 return } } // 当前主工具栏未开启 let mainToolIdentifier = parentIdentifier(identifier) if (mainToolIdentifier.isEmpty) { return } // 找到主工具栏 self.selectMainItem(mainToolIdentifier) DispatchQueue.main.async { // 再去选择子工具栏 self.selectChildItem(identifier) } } public func findItem(_ identifier: String) -> KMToolBoxItem? { if (isMainToolItem(identifier)) { return self.findMainItem(identifier) } return self.findChildItem(identifier) } // MARK: - // MARK: private Methods private func selectMainItem(_ identifier: String) { if (self.mainToolBarView?.toolbarItems == nil) { return } var item: KMToolBoxItem? for (key, value) in self.mainToolBarView!.toolbarItems { if (key == identifier) { item = (value as! KMToolBoxItem) break } } // 主工具栏 item if (item != nil) { if (identifier == KMDocumentAnnotationToolbarItemIdentifier || identifier == KMDocumentPageToolbarItemIdentifier || identifier == KMDocumentConversonToolbarItemIdentifier || identifier == KMDocumentScanOCRToolbarItemIdentifier || identifier == KMDocumentEditToolbarItemIdentifier || identifier == KMDocumentFormToolbarItemIdentifier || identifier == KMDocumentFillSginToolbarItemIdentifier || identifier == KMDocumentToolToolbarItemIdentifier) { self.mainToolBarView?.leftControllButtonAction(item: item!.clickButton) } else if (identifier == KMRightControlToolbarItemIdentifier) { self.mainToolBarView?.rightPanelControllButtonAction(item: item!.clickButton) } else if (identifier == KMLeftControlToolbarItemIdentifier) { item?.isSelected = !item!.isSelected self.delegate?.toolbarViewController?(self.mainToolBarView!, leftPanel: item!) } return } } private func trySelectChildItem(_ identifier: String) -> Bool { // 子工具栏 item [当前主工具栏已开启] var item: KMToolBoxItem? if (self.childToolBarView?.toolbarItems != nil && self.childToolBarView!.toolbarItems.count > 0) { for (key, value) in self.childToolBarView!.toolbarItems { if (key == identifier) { item = (value as! KMToolBoxItem) break } } // 子工具栏[找到] if (item != nil) { self.selectChildItem(identifier) return true } } return false } private func selectChildItem(_ identifier: String) { // 子工具栏 item [当前主工具栏已开启] var item: KMToolBoxItem? if (self.childToolBarView?.toolbarItems != nil && self.childToolBarView!.toolbarItems.count > 0) { for (key, value) in self.childToolBarView!.toolbarItems { if (key == identifier) { item = (value as! KMToolBoxItem) break } } // 子工具栏[找到] if (item != nil) { if (identifier == KMToolbarMoveToolModeItemIdentifier || identifier == KMToolbarMagnifyToolModeItemIdentifier || identifier == KMToolbarSelectToolModeItemIdentifier || identifier == KMToolbarZoomToSelectionItemIdentifier) { self.childToolBarView?.leftControllButtonAction(item: item!.clickButton) } else { self.childToolBarView?.changeAnnotationMode(item: item!.clickButton) } } } } private func findMainItem(_ identifier: String) -> KMToolBoxItem? { if (self.mainToolBarView?.toolbarItems == nil) { return nil } var item: KMToolBoxItem? if (isMainToolItem(identifier)) { for (key, value) in self.mainToolBarView!.toolbarItems { if (key == identifier) { item = (value as! KMToolBoxItem) break } } return item } return nil } private func findChildItem(_ identifier: String) -> KMToolBoxItem? { if (self.childToolBarView?.toolbarItems == nil || self.childToolBarView!.toolbarItems.count == 0) { return nil } var item: KMToolBoxItem? for (key, value) in self.childToolBarView!.toolbarItems { if (key == identifier) { item = (value as! KMToolBoxItem) break } } return item } func exitPageEdit() -> Void { resetToolbarViewController(mainToolBarView!) exitPageEditToolbarViewController(mainToolBarView!) } func exitTextEdit() -> Void { secondaryToolBarBox.isHidden = true secondaryToolBarHeight.constant = 50 bottomOffset.constant = 51 childToolBarBox.isHidden = false self.delegate?.toolbarController?(self, heightOffsetChange: 102) } func enterWatermarkAdjective(_ type: KMToolbarType, _ itemTitles: Array>) { self.toolbarType = .None let topBarView = KMWatermarkAdjectiveTopBarView() topBarView.frame = (self.mainToolBarView?.toolbar.bounds)! self.mainToolBarView?.toolbar.addSubview(topBarView) topBarView.autoresizingMask = NSView.AutoresizingMask(rawValue: 18) topBarView.wantsLayer = true topBarView.layer?.backgroundColor = NSColor.white.cgColor topBarView.isCanApply(can: false) var itemModels: Array> = [] for items in itemTitles { var array: Array = [] for title in items { let model = KMWatermarkAdjectiveTopBarItemModel() model.iconName = "" model.itemTitle = title array.append(model) } itemModels.append(array) } topBarView.initItemData(itemArrays: itemModels) topBarView.cancelClick = { [unowned self] in self.delegate?.clickChildTool!(type: type, index: 1) } topBarView.applyClick = { [unowned self] in self.delegate?.clickChildTool!(type: type, index: 2) } topBarView.itemClick = { [unowned self] (section: Int, item: Int) -> () in self.delegate?.clickChildTool!(type: type, index: 3+item) } } func exitWatermarkAdjective() { let topBarView = self.mainToolBarView?.toolbar.subviews.last if (topBarView == nil || topBarView?.isKind(of: KMWatermarkAdjectiveTopBarView.self) == false) { return } topBarView?.removeFromSuperview() } func fetchTopBarView() -> NSView? { let topBarView = self.mainToolBarView?.toolbar.subviews.last if (topBarView == nil) { return nil } if (topBarView?.isKind(of: KMWatermarkAdjectiveTopBarView.self) == true) { return topBarView } if (topBarView?.isKind(of: KMRedactTopToolBar.self) == true) { return topBarView } return nil } func enterRedact() { self.toolbarType = .None let topBarView = KMRedactTopToolBar() topBarView.frame = (self.mainToolBarView?.toolbar.bounds)! self.mainToolBarView?.toolbar.addSubview(topBarView) topBarView.autoresizingMask = NSView.AutoresizingMask(rawValue: 18) topBarView.wantsLayer = true topBarView.layer?.backgroundColor = NSColor.white.cgColor topBarView.selectItem(0) self.delegate?.clickChildTool!(type: .redact, index: 4) topBarView.itemClick = { [weak self] index in self!.delegate?.clickChildTool!(type: .redact, index: index) } } func exitRedact() { let topBarView = self.mainToolBarView?.toolbar.subviews.last if (topBarView == nil || topBarView?.isKind(of: KMRedactTopToolBar.self) == false) { return } topBarView?.removeFromSuperview() } // MARK: NSNotification @objc func selectedShapAnnotationChangeNotification(_ notification: Notification) -> Void { } @objc func PDFChangedNotification(_ notification: Notification) -> Void { } @objc func PDFTextEditPDFChangedNotification(_ notification: Notification) -> Void { } // MARK: func resetToolbarViewController(_ toolbarViewController: KMToolbarViewController) -> Void { self.toolbarType = .None self.mainToolBarView?.resetToolbar() self.mainViewController?.listView.annotationType = .unkown } func exitPageEditToolbarViewController(_ toolbarViewController: KMToolbarViewController) -> Void { } // MARK: item actions @objc func cropItemAction(sender: NSMenuItem) { if (sender.tag == 0) { /// 裁剪当前页面 self.delegate?.clickChildTool!(type: .crop, index: 1) return } if (sender.tag == 1) { /// 裁剪所有页面 self.delegate?.clickChildTool!(type: .crop, index: 2) return } /// 自定义裁剪区域 self.delegate?.clickChildTool!(type: .crop, index: 3) } @objc func secureItemAction(sender: NSMenuItem) { var index: Int = 1 if (sender.tag == 1) { /// 删除安全性设置 index = 2 } self.delegate?.clickChildTool?(type: .secure, index: index) } } extension KMToolbarController: KMToolbarViewControllerDelegate { func changeAnnotationModeAction(item: KMToolbarClickButton) { let type = CAnnotationType(rawValue: item.tag) ?? CAnnotationType.unkown if (type.isAdvanced() == false) { if self.toolbarType == .Magnify || self.toolbarType == .Move || self.toolbarType == .Select || self.toolbarType == .SelectZoom { self.toolbarType = .Annatiton } self.delegate?.changeAnnotationModeAction?(item: item) return } // 高级功能 Task { @MainActor in #if VERSION_DMG if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) let boxItem = item.clickObject as? KMToolBoxItem boxItem?.isSelected = false return } #endif //文字编辑 图片编辑 选中按钮逻辑(只能同时选中其中一个) if type == .addText || type == .addImage { let boxItem = item.clickObject as? KMToolBoxItem if boxItem != nil { if self.lastChildItemBox != boxItem { self.lastChildItemBox.isSelected = false boxItem!.isSelected = true } else { boxItem!.isSelected = !boxItem!.isSelected } self.lastChildItemBox = boxItem! } } if self.toolbarType == .Magnify || self.toolbarType == .Move || self.toolbarType == .Select || self.toolbarType == .SelectZoom { self.toolbarType = .Annatiton } self.delegate?.changeAnnotationModeAction?(item: item) } } func toolbarViewController(_ viewController: KMToolbarViewController, clickMode toolMode: KMToolbarViewType, toolbar toolbarItem: KMToolBoxItem, _ pages: [Int]) { let beforeModel = KMToolbarViewType(rawValue: self.lastItemBox.clickButton.tag) ?? .None if self.lastItemBox != nil { if (toolbarItem.isSelected && toolMode.isToolMode()) { // no nothings } else { self.lastItemBox.isSelected = false } } if self.lastChildItemBox != nil { if toolMode == .editPDF { if !self.lastItemBox.isSelected { self.lastChildItemBox.isSelected = false } } } if toolMode != .Magnify && toolMode != .Move && toolMode != .Select && toolMode != .SelectZoom && toolMode != .LeftPanel && toolMode != .RightPanel { if(toolMode == self.toolbarType) { toolbarItem.isSelected = false } else { toolbarItem.isSelected = true self.lastItemBox = toolbarItem } } else { if(toolMode != self.toolbarType && toolMode != .LeftPanel) { let item : KMToolBoxItem = (self.mainToolBarView?.toolbarItemFindItemIdentifiers(value: KMDocumentAnnotationToolbarItemIdentifier))! item.isSelected = true self.lastItemBox = item } else if (toolMode == .LeftPanel) { if(toolMode == self.toolbarType) { toolbarItem.isSelected = false } else { toolbarItem.isSelected = true } } } self.toolbarType = toolMode self.delegate?.mainToolDidClicked?(self, beforeModel, toolMode, toolbarItem, pages) } func toolbarViewController(_ viewController: KMToolbarViewController, rightPanel toolbarItem: KMToolBoxItem) { toolbarItem.isSelected = !toolbarItem.isSelected self.delegate?.toolbarViewController?(viewController, rightPanel: toolbarItem) } func toolbarViewController(_ viewController: KMToolbarViewController, leftPanel toolbarItem: KMToolBoxItem) { toolbarItem.isSelected = !toolbarItem.isSelected self.delegate?.toolbarViewController?(viewController, leftPanel: toolbarItem) } func showPDFLayoutModeAction(show: Bool) { self.delegate?.showPDFLayoutModeAction?(show: show) } func toolbarViewController(_ viewController: KMToolbarViewController, clickChaildToolType: KMToolbarType, toolbar toolbarItem: KMToolBoxItem) { if (clickChaildToolType == .crop) { let titles = [NSLocalizedString("Crop Current Page - White Margins", comment: ""), NSLocalizedString("Crop All Pages - Auto", comment: "")] let vc: KMHomePopViewController = KMHomePopViewController().initWithPopViewDataArr(titles) let createFilePopover: NSPopover = NSPopover.init() createFilePopover.contentViewController = vc createFilePopover.animates = true createFilePopover.behavior = .transient createFilePopover.setValue(true, forKey: "shouldHideAnchor") createFilePopover.show(relativeTo: NSZeroRect, of: toolbarItem, preferredEdge: .maxY) self.popover = createFilePopover vc.downCallback = { [weak self] (downEntered: Bool, count: String) -> Void in self?.popover?.close() self?.popover = nil if downEntered { if (count == titles.first) { self!.delegate?.clickChildTool?(type: .crop, index: 1) } else { self!.delegate?.clickChildTool?(type: .crop, index: 2) } } } } else if (clickChaildToolType == .bates || clickChaildToolType == .headerAndFooter || clickChaildToolType == .background || clickChaildToolType == .watermark) { toolbarItem.isSelected = false self.delegate?.clickChildTool?(type: clickChaildToolType, index: 0) } else if (clickChaildToolType == .redact) { toolbarItem.isSelected = false self.enterRedact() } else if (clickChaildToolType == .compress) { self.delegate?.clickChildTool?(type: .compress, index: 0) } else if (clickChaildToolType == .secure) { // toolbarItem.isSelected = fals let titles = [NSLocalizedString("Set Passwords", comment: ""), NSLocalizedString("Remove Security", comment: "")] let vc: KMHomePopViewController = KMHomePopViewController().initWithPopViewDataArr(titles) let createFilePopover: NSPopover = NSPopover.init() createFilePopover.contentViewController = vc createFilePopover.animates = true createFilePopover.behavior = .transient createFilePopover.setValue(true, forKey: "shouldHideAnchor") createFilePopover.show(relativeTo: CGRect(x: toolbarItem.bounds.origin.x, y: 10, width: toolbarItem.bounds.size.width, height: toolbarItem.bounds.size.height), of: toolbarItem, preferredEdge: .minY) vc.downCallback = { [weak self] (downEntered: Bool, count: String) -> Void in if downEntered { if (count == titles.first) { self!.delegate?.clickChildTool?(type: .secure, index: 1) } else { self!.delegate?.clickChildTool?(type: .secure, index: 2) } } } } else if ((KMToolbarType.word.rawValue ... KMToolbarType.conversion_image.rawValue).contains(clickChaildToolType.rawValue)) { /// 转档 self.delegate?.clickChildTool?(type: clickChaildToolType, index: 0) } else if (clickChaildToolType == .merge) { self.delegate?.clickChildTool?(type: clickChaildToolType, index: 0) } } func toolbarViewController(_ viewController: KMToolbarViewController, zoomModel selectedTag: Int) { self.delegate?.toolbarViewController?(viewController, zoomModel: selectedTag) } func toolbarViewController(_ viewController:KMToolbarViewController, zoomSting : String) { self.delegate?.toolbarViewController?(viewController, zoomSting: zoomSting) } func changePDFViewZoomInAction() { self.delegate?.changePDFViewZoomInAction?() } func changePDFViewZoomOutAction() { self.delegate?.changePDFViewZoomOutAction?() } func changePDFViewGotoNextPageAction() { self.delegate?.changePDFViewGotoNextPageAction?() } func changePDFViewGoToPreviousPageAction() { self.delegate?.changePDFViewGoToPreviousPageAction?() } func changePDFViewGotoBackAction() { self.delegate?.changePDFViewGotoBackAction?() } func changePDFViewGoToForwardAction() { self.delegate?.changePDFViewGoToForwardAction?() } func showPDFViewPrintViewController() { self.delegate?.showPDFViewPrintViewController?() } func aiTranslationPDFFileAction() { self.delegate?.aiTranslationPDFFileAction?() } func toolbarViewController(_ viewController: KMToolbarViewController, shareAction toolbarItem: KMToolBoxItem) { self.delegate?.toolbarViewController?(viewController, shareAction: toolbarItem) } func toolbarViewController(_ viewController: KMToolbarViewController, shareDocument item: NSMenuItem) { self.delegate?.toolbarViewController?(viewController, shareDocument: item) } func toolbarViewController(_ viewController: KMToolbarViewController, shareFlatten item: NSMenuItem) { self.delegate?.toolbarViewController?(viewController, shareFlatten: item) } func toolbarViewController(_ viewController: KMToolbarViewController, shareOriginalPDF item: NSMenuItem) { self.delegate?.toolbarViewController?(viewController, shareOriginalPDF: item) } func toolbarViewController(_ viewController: KMToolbarViewController, scanOCRModel selectedTag: Int) { self.delegate?.toolbarViewController?(viewController, scanOCRModel: selectedTag) } }