// // KMLeftSideViewController.swift // PDF Master // // Created by lxy on 2022/10/10. // import Cocoa @objc protocol KMLeftSideViewControllerDelegate { @objc optional func controlStateChange(_ obj: KMLeftSideViewController,show:Bool) @objc optional func enterEditMode(_ obj: KMLeftSideViewController, _ pages: [Int]) @objc optional func searchAction(searchString:String, isCase:Bool) @objc optional func controller(_ controller: KMLeftSideViewController, dispayDidChange dispay: KMPDFDisplayType) @objc optional func controller(controller: KMLeftSideViewController, itemClick item: Any?, itemKey: KMItemKey, params: Any?) @objc optional func controller(controller: KMLeftSideViewController, bookMarkDidChange bookMarks: [KMBookMarkItem]) } class KMLeftSideViewController: NSViewController { var listView : CPDFListView! @IBOutlet weak var leftTableview: NSTableView! @IBOutlet weak var contentBox: NSBox! @IBOutlet weak var leftBox: NSBox! lazy var thumbnailViewController : KMThumbnailViewController = { let thumbnailViewController = KMThumbnailViewController() return thumbnailViewController }() lazy var outlineViewController : KMOutlineViewController = { let outlineViewController = KMOutlineViewController() return outlineViewController }() lazy var annotationViewController : KMAnnotationViewController = { let annotationViewController = KMAnnotationViewController() return annotationViewController }() lazy var bookViewController : KMBookMarkViewController = { let bookViewController = KMBookMarkViewController() bookViewController.bookMarkDidChange = { [unowned self] (controller, bookMarks) in self.delegate?.controller?(controller: self, bookMarkDidChange: bookMarks) } return bookViewController }() lazy var fromViewController : KMFromViewController = { let fromViewController = KMFromViewController() return fromViewController }() lazy var searchViewController : KMSearchViewController = { let searchViewController = KMSearchViewController() return searchViewController }() lazy var signatureViewController : KMSignatureViewController = { let signatureViewController = KMSignatureViewController() return signatureViewController }() lazy var panelSetViewController : KMPDFViewPanelSetViewController = { let panelSetViewController = KMPDFViewPanelSetViewController() panelSetViewController.delegate = self return panelSetViewController }() var dataSource : [KMLeftMethodMode] = [KMLeftMethodMode]() var type : KMLeftMethodMode = KMLeftMethodMode() var isShowPanel : Bool = false var norImage : [String] = [] var selectImage : [String] = [] var mainVC: KMMainViewController? //select page var selectPages: [Int]? open weak var delegate: KMLeftSideViewControllerDelegate? convenience init(type : KMLeftMethodMode) { self.init() self.type = type } override func viewDidLoad() { super.viewDidLoad() self.leftBox.backgroundColor(NSColor(hex: "#F7F8FA")) self.leftTableview.backgroundColor(NSColor(hex: "#F7F8FA")) self.leftTableview.border(NSColor(hex: "#EDEEF0"),1 , 0) self.addMenuTitle() self.refreshShowMethod() } func showPanelView(show: Bool) { self.isShowPanel = show if show { self.panelSetViewController.listView = self.listView self.panelSetViewController.view.frame = self.view.frame self.view.addSubview(self.panelSetViewController.view) self.panelSetViewController.reloadListViewModel() self.panelSetViewController.view.autoresizingMask = [.height] } else { self.contentBox.isHidden = false self.panelSetViewController.view.removeFromSuperview() if self.type.methodType == .None { self.delegate?.controlStateChange?(self, show: false) } } } func refreshMethodType(methodType: BotaType) { if (self.isShowPanel) { self.showPanelView(show: false) return } let newType = KMLeftMethodMode() var show = true if self.type.methodType != methodType { newType.methodType = methodType } if self.type.methodType == methodType { show = false } self.type = newType; self.refreshShowMethod() self.delegate?.controlStateChange?(self,show:show) } private func updateViewButtonState() { switch self.type.methodType { case .None: do { self.contentBox.contentView = NSView() self.delegate?.controlStateChange?(self,show:false) } break case .Thumbnail: do { self.thumbnailViewController.listView = self.listView self.thumbnailViewController.delegate = self self.contentBox.contentView = self.thumbnailViewController.view self.thumbnailViewController.reloadData() } break case .Outline: do { self.outlineViewController.listView = self.listView self.contentBox.contentView = self.outlineViewController.view } break case .BookMark: do { self.bookViewController.listView = self.listView self.contentBox.contentView = self.bookViewController.view self.bookViewController.reloadData() } break case .Annotation: do { self.annotationViewController.listView = self.listView self.contentBox.contentView = self.annotationViewController.view // self.annotationViewController.reloadData() } break case .From: do { self.fromViewController.listView = self.listView self.contentBox.contentView = self.fromViewController.view self.fromViewController.reloadData() } break case .Search: do { self.searchViewController.listView = self.listView self.searchViewController.delegate = self self.contentBox.contentView = self.searchViewController.view // self.searchViewController.reloadData() } break case .Signature: do { self.signatureViewController.listView = self.listView self.contentBox.contentView = self.signatureViewController.view self.signatureViewController.reloadData() } break } } func refreshShowMethod() { self.dataSource = [KMLeftMethodMode]() norImage = [] selectImage = [] if KMBOTAManagerClass.shard.getMethodShow(key: thumbnailMethodKey) { let mode = KMLeftMethodMode() mode.methodName = thumbnailMethodKey mode.methodType = .Thumbnail self.dataSource.insert(mode, at: self.dataSource.count) norImage.append("KMImageNameSidebarThumbailNor") selectImage.append("KMImageNameSidebarThumbailSelect") } if KMBOTAManagerClass.shard.getMethodShow(key: outlineMethodKey) { let mode = KMLeftMethodMode() mode.methodName = outlineMethodKey mode.methodType = .Outline self.dataSource.insert(mode, at: self.dataSource.count) norImage.append("KMImageNameSidebarOutlineNor") selectImage.append("KMImageNameSidebarOutlineSelect") } if KMBOTAManagerClass.shard.getMethodShow(key: bookMarkMethodKey) { let mode = KMLeftMethodMode() mode.methodName = bookMarkMethodKey mode.methodType = .BookMark self.dataSource.insert(mode, at: self.dataSource.count) norImage.append("KMImageNameSidebarBookMarkNor") selectImage.append("KMImageNameSidebarBookMarkSelect") } if KMBOTAManagerClass.shard.getMethodShow(key: anntationMethodKey) { let mode = KMLeftMethodMode() mode.methodName = anntationMethodKey mode.methodType = .Annotation self.dataSource.insert(mode, at: self.dataSource.count) norImage.append("KMImageNameSidebarAnnotationNor") selectImage.append("KMImageNameSidebarAnnotationSelect") } if KMBOTAManagerClass.shard.getMethodShow(key: searchMethodKey) { let mode = KMLeftMethodMode() mode.methodName = searchMethodKey mode.methodType = .Search self.dataSource.insert(mode, at: self.dataSource.count) norImage.append("KMImageNameSidebarSearchNor") selectImage.append("KMImageNameSidebarSearchSelect") } // if KMBOTAManagerClass.shard.getMethodShow(key: formMethodKey) { // let mode = KMLeftMethodMode() // mode.methodName = formMethodKey // mode.methodType = .From // self.dataSource.insert(mode, at: self.dataSource.count) // } // if KMBOTAManagerClass.shard.getMethodShow(key: signatureMethodKey) { // let mode = KMLeftMethodMode() // mode.methodName = signatureMethodKey // mode.methodType = .Signature // self.dataSource.insert(mode, at: self.dataSource.count) // } var isConstant = false for source in dataSource { if self.type.methodType == source.methodType { isConstant = true } } if(!isConstant) { self.type = KMLeftMethodMode() } self.leftTableview.reloadData() var typeIndex = -1 for (index,value) in self.dataSource.enumerated() { if value.methodType == self.type.methodType { typeIndex = index } } self.leftTableview.selectRowIndexes([typeIndex], byExtendingSelection: true) if self.dataSource.count > 0 && typeIndex >= 0 { self.type = self.dataSource[typeIndex] } self.updateViewButtonState() } //MARK: menu private func addMenuTitle() { let menus : NSMenu = NSMenu(title: "") let addItem = self.menuItemWithTitle(title: NSLocalizedString("Thumbnails", comment: ""),type:thumbnailMethodKey,action: #selector(renameBookAction),tag: 1) let outlineItem = self.menuItemWithTitle(title: NSLocalizedString("Outline", comment: ""),type:outlineMethodKey,action: #selector(renameBookAction),tag: 2) let bookItem = self.menuItemWithTitle(title: NSLocalizedString("Bookmarks", comment: ""), type:bookMarkMethodKey,action: #selector(renameBookAction),tag: 3) let annationItem = self.menuItemWithTitle(title: NSLocalizedString("Annotations", comment: ""), type:anntationMethodKey,action: #selector(renameBookAction),tag: 4) let searchItem = self.menuItemWithTitle(title: NSLocalizedString("Search", comment: ""), type:searchMethodKey,action: #selector(renameBookAction),tag: 5) // let formItem = self.menuItemWithTitle(title: NSLocalizedString("域", comment: ""), type:formMethodKey,action: #selector(renameBookAction),tag: 6) // let signatureItem = self.menuItemWithTitle(title: NSLocalizedString("签名", comment: ""), type:signatureMethodKey,action: #selector(renameBookAction),tag: 7) menus.addItem(addItem) menus.addItem(outlineItem) menus.addItem(bookItem) menus.addItem(annationItem) menus.addItem(searchItem) // menus.addItem(formItem) // menus.addItem(signatureItem) self.leftTableview.menu = menus } func menuItemWithTitle(title:String,type:String,action:Selector?,tag:Int) -> NSMenuItem { let menuItem = NSMenuItem.init(title: title as String, action: action, keyEquivalent: "") menuItem.target = self menuItem.tag = tag if KMBOTAManagerClass.shard.getMethodShow(key: type) { menuItem.state = NSControl.StateValue.on } else { menuItem.state = NSControl.StateValue.off } return menuItem } @objc func renameBookAction(menuItem:NSMenuItem) { var show = true if menuItem.state == NSControl.StateValue.on { menuItem.state = NSControl.StateValue.off show = false } else { menuItem.state = NSControl.StateValue.on show = true } switch menuItem.tag { case 1: do { KMBOTAManagerClass.shard.setLeftMethod(show: show, key: thumbnailMethodKey) } case 2: do { KMBOTAManagerClass.shard.setLeftMethod(show: show, key: outlineMethodKey) } case 3: do { KMBOTAManagerClass.shard.setLeftMethod(show: show, key: bookMarkMethodKey) } case 4: do { KMBOTAManagerClass.shard.setLeftMethod(show: show, key: anntationMethodKey) } case 5: do { KMBOTAManagerClass.shard.setLeftMethod(show: show, key: searchMethodKey) } case 6: do { KMBOTAManagerClass.shard.setLeftMethod(show: show, key: formMethodKey) } case 7: do { KMBOTAManagerClass.shard.setLeftMethod(show: show, key: signatureMethodKey) } break default: break } self.refreshShowMethod() } } extension KMLeftSideViewController: KMThumbnailViewControllerDelegate { func gotoPageEdit(thumbnailViewController: KMThumbnailViewController, pages: [Int]) { self.delegate?.enterEditMode?(self, pages) } func pageDidSelect(controller: KMThumbnailViewController, pages: [Int]) { self.selectPages = pages } func controller(controller: KMThumbnailViewController, itemClick item: Any?, itemKey: KMItemKey, params: Any?) { self.delegate?.controller?(controller: self, itemClick: item, itemKey: itemKey, params: params) } } extension KMLeftSideViewController : KMSearchViewControllerDelegate { func searchAction(searchString: String,isCase:Bool) { self.delegate?.searchAction?(searchString: searchString, isCase: isCase) } func searchDoneAction(viewController: KMSearchViewController) { self.type = KMLeftMethodMode() self.updateViewButtonState() self.delegate?.controlStateChange?(self,show:false) self.leftTableview.reloadData() } } //MARK: NSTableViewDelegate,NSTableViewDataSource extension KMLeftSideViewController: NSTableViewDelegate,NSTableViewDataSource { func numberOfRows(in tableView: NSTableView) -> Int { return self.dataSource.count } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { let cell : KMLiftSideCellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMLiftSideCellView"), owner: self) as! KMLiftSideCellView if row <= selectImage.count-1 { if self.dataSource[row] == self.type { cell.isSelect = true cell.mothedImage.image = NSImage(named: selectImage[row]) cell.backgroundColor(NSColor(hex: "#DFE1E5")) } else { cell.isSelect = false cell.mothedImage.image = NSImage(named: norImage[row]) cell.backgroundColor(NSColor.clear) } } cell.index = row cell.buttonClick = { [unowned self] index in if ((index < self.dataSource.count) && (index > -1)) { let isSearch = self.type.methodType == .Search var show = true if( self.type == self.dataSource[index]) { self.type = KMLeftMethodMode() show = false } else { self.type = self.dataSource[index] show = true } self.updateViewButtonState() self.delegate?.controlStateChange?(self,show:show) self.leftTableview.selectRowIndexes([index], byExtendingSelection: true) self.leftTableview.reloadData() UserDefaults.standard.set(index, forKey: "KMBOTASelectedIndexKey") UserDefaults.standard.synchronize() if (isSearch && show == false) { self.view.window?.makeFirstResponder(self) } else if (isSearch && self.type.methodType != .Search) { // 切换 self.view.window?.makeFirstResponder(self) } } } return cell } func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { return 48 } func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { let rowView = KMCustomTableRowView() rowView.selectionColor = NSColor(calibratedRed: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1.0) rowView.color = NSColor(hex: "#F7F8FA") return rowView } func tableViewSelectionDidChange(_ notification: Notification) { } } extension KMLeftSideViewController: KMPDFViewPanelSetViewControllerDelegate { func controller(_ controller: KMPDFViewPanelSetViewController, dispayDidChange dispay: KMPDFDisplayType) { self.delegate?.controller?(self, dispayDidChange: dispay) } func controller(_ controller: KMPDFViewPanelSetViewController, pageBreaksClick pageBreaks: Bool) { self.listView?.displaysPageBreaks = pageBreaks self.listView?.layoutDocumentView() } func controller(_ controller: KMPDFViewPanelSetViewController, rotateClick rotateType: KMRotateType) { if (rotateType == .clockwise) { /// 顺时针 let page : CPDFPage = self.listView?.currentPage() ?? CPDFPage() if page.rotation == 0 { page.rotation = 90 } else if page.rotation == 90 { page.rotation = 180 } else if page.rotation == 180 { page.rotation = 270 } else if page.rotation == 270 { page.rotation = 0 } self.listView?.layoutDocumentView() } else if (rotateType == .anticlockwise) { /// 逆时针 let page : CPDFPage = self.listView?.currentPage() ?? CPDFPage() if page.rotation == 0 { page.rotation = 270 } else if page.rotation == 90 { page.rotation = 0 } else if page.rotation == 180 { page.rotation = 90 } else if page.rotation == 270 { page.rotation = 180 } self.listView?.layoutDocumentView() } } } // MARK: - // MARK: - 扩展 extension KMLeftSideViewController { public func selectType(_ type: BotaType) { // 更新 type var show = true if (self.type.methodType == .None) { show = true } else { if (self.type.methodType == type) { show = false } else { show = true } } var index: Int = NSNotFound switch type { case .None: index = NSNotFound break case .Thumbnail: index = 0 break case .Outline: index = 1 break case .BookMark: index = 2 break case .Annotation: index = 3 break case .Search: index = 4 break case .From: index = 5 break case .Signature: index = 6 break } self.type = self.getMethodMode(show ? type : .None) // 更新按钮状态 self.updateViewButtonState() // 将事件传递出去 self.delegate?.controlStateChange?(self,show:show) if (index != NSNotFound) { self.leftTableview.selectRowIndexes([index], byExtendingSelection: true) // 记录当前选中 UserDefaults.standard.set(index, forKey: "KMBOTASelectedIndexKey") UserDefaults.standard.synchronize() } self.leftTableview.reloadData() } private func getMethodMode(_ type: BotaType) -> KMLeftMethodMode { let mode = KMLeftMethodMode() mode.methodType = type switch type { case .None: mode.methodName = "" break case .Thumbnail: mode.methodName = thumbnailMethodKey break case .Outline: mode.methodName = outlineMethodKey break case .BookMark: mode.methodName = bookMarkMethodKey break case .Annotation: mode.methodName = anntationMethodKey break case .Search: mode.methodName = searchMethodKey break case .From: mode.methodName = formMethodKey break case .Signature: mode.methodName = signatureMethodKey break } return mode } } //MARK: Cache extension KMLeftSideViewController { func clearAnnotationFilterData() { let userDefaults = UserDefaults.standard let typeData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false) userDefaults.set(typeData, forKey: "KMNoteOutlineFilterSelectArray_Type" + self.listView.document.documentURL.path) let colorData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false) userDefaults.set(colorData, forKey: "KMNoteOutlineFilterSelectArray_Color" + self.listView.document.documentURL.path) let authorData = try?NSKeyedArchiver.archivedData(withRootObject: [Any](), requiringSecureCoding: false) userDefaults.set(authorData, forKey: "KMNoteOutlineFilterSelectArray_Author" + self.listView.document.documentURL.path) userDefaults.synchronize() } func clearNotification() { self.bookViewController.removeNotification() self.annotationViewController.removeNotification() self.outlineViewController.removeNotification() self.thumbnailViewController.removeNotification() } }