1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666 |
- //
- // KMLeftSideViewController.swift
- // PDF Reader Pro
- //
- // Created by lxy on 2022/10/10.
- //
- import Cocoa
- import KMComponentLibrary
- // MARK: - KMBotaAnnotationHeaderView
- class KMBotaAnnotationHeaderView: NSView {
- private lazy var titleLabel_: NSTextField = {
- let view = NSTextField(labelWithString: "")
- view.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-bold")
- view.textColor = KMNColorTools.colorText_2()
- return view
- }()
-
- private lazy var searchButton_: ComponentButton = {
- let view = ComponentButton()
- let prop = ComponentButtonProperty()
- prop.type = .text_gray
- prop.size = .xxs
- prop.onlyIcon = true
- prop.icon = NSImage(named: "KMImageNameOutlineSearch")
- view.properties = prop
- return view
- }()
-
- private lazy var sortButton_: ComponentButton = {
- let view = ComponentButton()
- let prop = ComponentButtonProperty()
- prop.type = .text_gray
- prop.size = .xxs
- prop.onlyIcon = true
- prop.icon = NSImage(named: "KMImageNameBotaSearch")
- view.properties = prop
- return view
- }()
-
- private lazy var moreButton_: ComponentButton = {
- let view = ComponentButton()
- let prop = ComponentButtonProperty()
- prop.type = .text_gray
- prop.size = .xxs
- prop.onlyIcon = true
- prop.icon = NSImage(named: "KMImageNameOutlineMore")
- view.properties = prop
- return view
- }()
-
- private lazy var bottomLine_: NSView = {
- let view = NSView()
- view.wantsLayer = true
- return view
- }()
-
- var titleLabel: NSTextField {
- get {
- return titleLabel_
- }
- }
-
- var searchButton: ComponentButton {
- get {
- return searchButton_
- }
- }
- var sortButton: ComponentButton {
- get {
- return sortButton_
- }
- }
- var moreButton: ComponentButton {
- get {
- return moreButton_
- }
- }
- var bottomLine: NSView {
- get {
- return bottomLine_
- }
- }
-
- var itemClick: KMCommonClickBlock?
-
- convenience init() {
- self.init(frame: .init(x: 0, y: 0, width: 300, height: 40))
-
- initSubviews()
- }
-
- override func awakeFromNib() {
- super.awakeFromNib()
-
- initSubviews()
- }
- func initSubviews() {
- let margin: CGFloat = 12
- addSubview(titleLabel_)
- titleLabel_.km_add_leading_constraint(constant: margin)
- titleLabel_.km_add_centerY_constraint()
-
- let vspace: CGFloat = 8
- let wh: CGFloat = 24
- addSubview(moreButton_)
- moreButton_.km_add_size_constraint(size: .init(width: wh, height: wh))
- moreButton_.km_add_trailing_constraint(constant: -margin)
- moreButton_.km_add_centerY_constraint()
- moreButton_.setTarget(self, action: #selector(moreAction))
-
- addSubview(sortButton_)
- sortButton_.km_add_size_constraint(size: .init(width: wh, height: wh))
- sortButton_.km_add_trailing_constraint(equalTo: moreButton_, attribute: .leading, constant: -vspace)
- sortButton_.km_add_centerY_constraint()
- sortButton_.setTarget(self, action: #selector(sortAction))
-
- addSubview(searchButton_)
- searchButton_.km_add_size_constraint(size: .init(width: wh, height: wh))
- searchButton_.km_add_trailing_constraint(equalTo: sortButton_, attribute: .leading, constant: -vspace)
- searchButton_.km_add_centerY_constraint()
- searchButton_.setTarget(self, action: #selector(searchAction))
-
- addSubview(bottomLine_)
- bottomLine_.km_add_leading_constraint()
- bottomLine_.km_add_trailing_constraint()
- bottomLine_.km_add_bottom_constraint()
- bottomLine_.km_add_height_constraint(constant: 1)
- }
-
- @objc func searchAction() {
- itemClick?(1)
- }
-
- @objc func sortAction() {
- itemClick?(2)
- }
-
- @objc func moreAction() {
- itemClick?(3)
- }
- }
- // MARK: - KMLeftSideViewControllerDelegate
- @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, itemClick item: Any?, itemKey: KMItemKey, params: Any?)
-
- @objc optional func controller(controller: KMLeftSideViewController, rotateType: KMRotateType)
-
- @objc optional func controller(controller: KMLeftSideViewController, listViewSelectionDidChange object: Any?, info: [String : Any]?)
-
- @objc optional func listViewThumPageIndeDidChange(controller: KMLeftSideViewController, pageIndexs: IndexSet)
- }
- extension KMLeftSideViewController.Key {
- static let disableTableToolTipsKey = "SKDisableTableToolTips"
- }
- class KMLeftSideViewController: KMSideViewController {
-
- @IBOutlet var searchViewController: KMBotaSearchViewController!
- @IBOutlet weak var toolButtonBox: NSBox!
- @IBOutlet weak var toolButtonBoxLayoutConstraint: NSLayoutConstraint!
- @IBOutlet var noteOutlineView: KMNoteOutlineView!
-
- var bookmarkViewC: KMBookMarkViewController?
- var noteFilterButtonHoverView = KMHoverView()
- var noteFilterSelected = false
-
- var stopRepeatLoad: Bool = false
- var dataUpdating = false
- @IBOutlet weak var leftListView: NSView!
- @IBOutlet weak var toolHeaderBox: NSBox!
- var noteFilterMenu:NSMenu?
-
- var isFirst = false //打开阅读页初始化
-
- var isShowPanel : Bool = false
- weak var delegate: KMLeftSideViewControllerDelegate?
-
- let noteColumnId = NSUserInterfaceItemIdentifier(rawValue: "note")
- let authorColumnId = NSUserInterfaceItemIdentifier(rawValue: "author")
-
- struct Key {}
-
- var mwcFlags: MwcFlags = MwcFlags()
- let scalingIncrement: Float = 0.1
-
- var filterButtonLayer: NSView?
-
- // 注释
- var noteTypeDict: [String : Any] = [:]
- private var _noteSortType: KMNoteSortType = .none
- var noteSortType: KMNoteSortType {
- get {
- return self._noteSortType
- }
- set {
- self._noteSortType = newValue
-
- NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMAnnotationSortTypeKeyNotification"), object: self)
- }
- }
-
- var isAscendSort = false {
- didSet {
- NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMAnnotationSortTypeKeyNotification"), object: self)
- }
- }
-
- var headerView: KMNBotaAnnotationHeaderView = {
- let view = KMNBotaAnnotationHeaderView()
- return view
- }()
-
- var isRenameNoteOutline = false
-
- var currentItem: Any?
- // 所有注释
- var allAnnotations: [CPDFAnnotation] = []
- // 注释搜索模式标记
- var noteSearchMode = false
- // 注释搜索数组
- var noteSearchArray: [KMBotaAnnotationBaseModel] = []
- // 注释搜索 忽略大小写标识
- var caseInsensitiveNoteSearch = false
- // 注释列表数据源
- var annoListModel: KMAnnotationListModel?
- var editNoteTextField: NSTextField?
- weak var editNote: CPDFAnnotation?
-
- var leftMargin: CGFloat = 0
-
- var dragIn = false
-
- private var deletePages_ = Set<CPDFPage>()
-
- let userFbHanddler = KMUserFeekbackHanddler()
- let noteReplyHanddler = KMNoteReplyHanddler()
-
- var searchGroupView: ComponentGroup?
- var searchGroupTarget: ComponentButton?
- var moreGroupView: ComponentGroup?
- var rightGroupView: ComponentGroup?
- var emptyView: ComponentEmpty = {
- let view = ComponentEmpty()
- view.properties = ComponentEmptyProperty(emptyType: .noAnnotation, state: .normal, image: NSImage(named: "KMImageNameEmptyAnnotate"), text: KMLocalizedString("No Annotations"), subText: "")
- return view
- }()
-
- private lazy var headerSearchView_: KMNBotaHeaderSearchView? = {
- let view = KMNBotaHeaderSearchView.createFromNib()
- return view
- }()
-
- var headerSearchView: KMNBotaHeaderSearchView? {
- get {
- return headerSearchView_
- }
- }
- deinit {
- KMPrint("KMLeftSideViewController deinit.")
-
- NotificationCenter.default.removeObserver(self)
- DistributedNotificationCenter.default().removeObserver(self)
- }
-
- override var nibName: NSNib.Name? {
- return "LeftSideView"
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- noteReplyHanddler.viewC = self
- }
-
- override func loadView() {
- super.loadView()
-
- searchViewController.loadView()
- note_initSubViews()
- note_initDefalutValue()
- displayEmptyViewAnimating(false)
- displayNoteViewAnimating(false)
-
- hideHeaderSearch()
- toolHeaderBox.borderWidth = 0
- toolHeaderBox.contentView = headerView
- headerView.itemClick = { [weak self] idx, _ in
- if idx == 1 {
- self?.showHeaderSearch()
- } else if idx == 2 {
- self?.showFilterController()
- } else if idx == 3 {
- self?.showMoreGroupView()
- }
- }
-
- headerSearchView?.itemClick = { [weak self] idx, params in
- if idx == 1 { // 显示搜索限制条件
- guard let button = params.first as? ComponentButton else {
- return
- }
- self?.showSearchGroupView(sender: button)
- } else if idx == 2 { // 关闭搜索
- self?.hideHeaderSearch()
- self?.noteSearchMode = false
- self?.reloadAnnotation()
- }
- }
- headerSearchView?.valueDidChange = { [weak self] sender, info in
- let value = info?[.newKey] as? String ?? ""
- self?.noteSearchMode = !value.isEmpty
- self?.updateNoteFilterPredicate(searchString: value)
- }
- }
-
- override func updateUILanguage() {
- super.updateUILanguage()
-
- KMMainThreadExecute {
- self.headerView.titleLabel.stringValue = KMLocalizedString("Annotation")
- }
- }
-
- override func updateUIThemeColor() {
- super.updateUIThemeColor()
-
- KMMainThreadExecute {
- self.headerView.titleLabel.textColor = KMNColorTools.colorText_2()
- self.headerView.searchButton.properties.icon = NSImage(named: "KMImageNameOutlineSearch")
- self.headerView.searchButton.reloadData()
- self.headerView.sortButton.properties.icon = NSImage(named: "KMImagenameBotaAnnotationFilter")
- self.headerView.sortButton.reloadData()
- self.headerView.moreButton.properties.icon = NSImage(named: "KMImageNameOutlineMore")
- self.headerView.moreButton.reloadData()
- self.headerView.bottomLine.layer?.backgroundColor = KMNColorTools.colorBorder_divider().cgColor
- }
- }
-
- func showHeaderSearch() {
- toolHeaderBox.contentView = headerSearchView
-
- headerView.searchButton.properties.state = .normal
- headerView.searchButton.reloadData()
- }
-
- func hideHeaderSearch() {
- toolHeaderBox.contentView = headerView
- }
-
- func updateMarkState(model:KMBotaAnnotationModel){ // Markup
- let anno = model.anno
- guard let state = self.noteReplyHanddler.fetchAnnoState(anno), state == .marked else {
- self.noteReplyHanddler.markAnnotation(anno)
- self.noteOutlineView.reloadItem(model)
- return
- }
- self.noteReplyHanddler.unMarkAnnotation(anno)
- self.noteOutlineView.reloadItem(model)
- }
-
- func updateReplaState(model:KMBotaAnnotationModel,state:CPDFAnnotationState){
- let anno = model.anno
- noteReplyHanddler.updateAnnoState(anno: anno, state: state)
- self.noteOutlineView.reloadData()
- }
-
- func updateExpand (model: KMBotaAnnotationModel, isExpand: Bool, item: Any) {
- // 将折叠状态记录到模型
- model.foldType = isExpand ? .unfold : .fold
-
- model.footerModel?.isExpand = isExpand
- model.isExpand = isExpand
- self.noteOutlineView.reloadData()
- DispatchQueue.main.async {
- let row = self.noteOutlineView.row(forItem: item)
- self.noteOutlineView.scrollRowToVisible(row)
- }
- }
-
- // MARK: - Filter
- func showFilterController() {
- noteFilterAction(nil)
- }
-
- // MARK: - Group View
- func showMoreGroupView() {
- let groupView = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
-
- var expand_MenuString = KMLocalizedString("Collapse All")
- for secM in self.annoListModel?.datas ?? [] {
- if secM.isExpand == false {
- expand_MenuString = KMLocalizedString("Expand All")
- break
- }
- }
- let hasAnno = self.allAnnotations.count >= 1
- let disable = !hasAnno
-
- let expand_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(isDisabled:disable, text: expand_MenuString,
- identifier: BOTAMenuIdentifier_Annotation_Expand)
- let sort_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Sort"),
- identifier: BOTAMenuIdentifier_Annotation_Sort)
-
- var subMenuItemArr: [ComponentMenuitemProperty] = []
- let pageProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(isDisabled:disable,text: KMLocalizedString("By Page"),identifier: BOTAMenuIdentifier_Annotation_SortPage)
- let timeAscProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(isDisabled:disable,text: KMLocalizedString("By Time - Ascending"),identifier: BOTAMenuIdentifier_Annotation_SortAscTime)
- let timeDecProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(
- isDisabled:disable,text: KMLocalizedString("By Time - Descending"),identifier: BOTAMenuIdentifier_Annotation_SortDesTime)
-
- subMenuItemArr.append(pageProperty)
- subMenuItemArr.append(timeAscProperty)
- subMenuItemArr.append(timeDecProperty)
- sort_Menuitem.subPropertys = subMenuItemArr
- let improt_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Import Annotations"),
- identifier: BOTAMenuIdentifier_Annotation_Improt)
-
- let exprot_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(isDisabled:disable,text: KMLocalizedString("Export Annotations"),
- identifier: BOTAMenuIdentifier_Annotation_Export)
-
- let rem_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(isDisabled:disable,text: KMLocalizedString("Remove All Annotations"),
- identifier: BOTAMenuIdentifier_Annotation_RemoveAll)
- let delete_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(isDisabled:disable,text: KMLocalizedString("Delete All Reply"),
- identifier: BOTAMenuIdentifier_Annotation_DeleteRep)
-
- var menuItemArr: [ComponentMenuitemProperty] = []
- menuItemArr.append(expand_Menuitem)
- menuItemArr.append(sort_Menuitem)
- menuItemArr.append(improt_Menuitem)
- menuItemArr.append(exprot_Menuitem)
- menuItemArr.append(rem_Menuitem)
- menuItemArr.append(delete_Menuitem)
- moreGroupView = groupView
- groupView?.groupDelegate = self
- groupView?.frame = CGRectMake(310, 0, 200, 36.0 * CGFloat(menuItemArr.count))
- groupView?.updateGroupInfo(menuItemArr)
-
- var point = NSPoint(x: CGRectGetMaxX(headerView.moreButton.frame), y: CGRectGetMidY(headerView.moreButton.frame))
- point = headerView.convert(point, to: nil)
- point.y -= (groupView?.frame.size.height ?? 0)/2
- groupView?.showWithPoint(point, relativeTo: headerView.moreButton)
- }
-
- func showRightGropView(raw: Int,event:NSEvent,view:NSView?,item:Any) {
- let groupView = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
-
- currentItem = item
-
- var menuItemArr: [ComponentMenuitemProperty] = []
- let rowIndexes = self.selectedObjcNotes()
-
- var viewHeight = 0.0
- if(rowIndexes.count == 1) {
- let dataItem = rowIndexes.first
- if let data = dataItem as? KMBotaAnnotationModel {
- if let an = data.anno as? CPDFAnnotation {
- if an.isKind(of: CPDFFreeTextAnnotation.self) == true ||
- an.isKind(of: CPDFTextAnnotation.self) == true {
- } else {
- let note_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Edit"),
- identifier: BOTAMenuIdentifier_Annotation_EditNote,representedObject: [data])
- menuItemArr.append(note_Menuitem)
- viewHeight += 36.0
- }
- let reply_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Reply"),
- identifier: BOTAMenuIdentifier_Annotation_AddRep,representedObject: [data])
- menuItemArr.append(reply_Menuitem)
- viewHeight += 36.0
- let state = self.noteReplyHanddler.fetchAnnoState(an) ?? .unMarked
- var markString = ""
- if state == .unMarked {
- markString = KMLocalizedString("Marked")
- } else {
- markString = KMLocalizedString("Unmarked")
- }
- let mark_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: markString,
- identifier: BOTAMenuIdentifier_Annotation_AddMark,representedObject: [data])
- menuItemArr.append(mark_Menuitem)
- viewHeight += 36.0
-
- let state_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Status"),
- identifier: BOTAMenuIdentifier_Annotation_RepState)
-
- var subMenuItemArr: [ComponentMenuitemProperty] = []
- let property0: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("None"),identifier: BOTAMenuIdentifier_Annotation_RepStateNone,representedObject: [data])
- let property1: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Accepted"),identifier: BOTAMenuIdentifier_Annotation_RepStateAccepted,representedObject: [data])
- let property2: ComponentMenuitemProperty = ComponentMenuitemProperty(
- text: KMLocalizedString("Rejected"),identifier: BOTAMenuIdentifier_Annotation_RepStateRejected,representedObject: [data])
- let property3: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Cancelled"),identifier: BOTAMenuIdentifier_Annotation_RepStateCancelled,representedObject: [data])
- let property4: ComponentMenuitemProperty = ComponentMenuitemProperty(
- text: KMLocalizedString("Completed"),identifier: BOTAMenuIdentifier_Annotation_RepStateCompleted,representedObject: [data])
- subMenuItemArr.append(property0)
- subMenuItemArr.append(property1)
- subMenuItemArr.append(property2)
- subMenuItemArr.append(property3)
- subMenuItemArr.append(property4)
-
- let reviewState = noteReplyHanddler.fetchReviewState(an) ?? .none
- if reviewState == .none {
- property0.righticon = NSImage(named: "KMNImageNameMenuSelect")
- } else if reviewState == .completed {
- property4.righticon = NSImage(named: "KMNImageNameMenuSelect")
- } else if reviewState == .canceled {
- property3.righticon = NSImage(named: "KMNImageNameMenuSelect")
- } else if reviewState == .accepted {
- property1.righticon = NSImage(named: "KMNImageNameMenuSelect")
- } else if reviewState == .rejected {
- property2.righticon = NSImage(named: "KMNImageNameMenuSelect")
- }
-
- state_Menuitem.subPropertys = subMenuItemArr
- menuItemArr.append(state_Menuitem)
- viewHeight += 36.0
-
- menuItemArr.append(ComponentMenuitemProperty.divider())
- viewHeight += 8.0
- var showString = ""
- if data.isExpand {
- showString = KMLocalizedString("Collapse")
- } else {
- showString = KMLocalizedString("Expand")
- }
-
- let show_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: showString,
- identifier: PDFViewMenuIdentifier_Normal_ShowPopUI,representedObject: [data])
- menuItemArr.append(show_Menuitem)
- viewHeight += 36.0
-
- menuItemArr.append(ComponentMenuitemProperty.divider())
- viewHeight += 8.0
- if an.isKind(of: CPDFFreeTextAnnotation.self) == true ||
- an.isKind(of: CPDFTextAnnotation.self) == true ||
- an.isKind(of: CPDFMarkupAnnotation.self) == true {
- let copy_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Copy Text"),
- identifier: PDFViewMenuIdentifier_Normal_Copy,representedObject: [data])
- copy_Menuitem.keyEquivalent = "⌘ C"
- menuItemArr.append(copy_Menuitem)
- viewHeight += 36.0
- }
-
- let delete_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Delete"),
- identifier: PDFViewMenuIdentifier_Normal_Delete,representedObject: [data])
- delete_Menuitem.keyEquivalent = "⌘ " + "⌫"
- menuItemArr.append(delete_Menuitem)
- viewHeight += 36.0
- }
- } else if let replyModel = dataItem as? KMBotaAnnotationReplyModel {
- let note_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Edit"),
- identifier: BOTAMenuIdentifier_Annotation_EditNote,representedObject: [replyModel])
- menuItemArr.append(note_Menuitem)
- viewHeight += 36.0
-
- let showString = KMLocalizedString("Collapse")
- let show_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: showString,
- identifier: PDFViewMenuIdentifier_Normal_ShowPopUI,representedObject: [replyModel])
- menuItemArr.append(show_Menuitem)
- viewHeight += 36.0
- menuItemArr.append(ComponentMenuitemProperty.divider())
- viewHeight += 8.0
-
- let copy_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Copy Text"),
- identifier: PDFViewMenuIdentifier_Normal_CopyText,representedObject: [replyModel])
- copy_Menuitem.keyEquivalent = "⌘ C"
- menuItemArr.append(copy_Menuitem)
- viewHeight += 36.0
-
- let delete_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Delete"),
- identifier: BOTAMenuIdentifier_Annotation_DeleteSignRep,representedObject: [replyModel])
- delete_Menuitem.keyEquivalent = "⌘ " + "⌫"
- menuItemArr.append(delete_Menuitem)
- viewHeight += 36.0
- }
- } else if rowIndexes.count > 1 {
- let delete_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Delete"),
- identifier: BOTAMenuIdentifier_Annotation_DeleteMuteRep,representedObject: rowIndexes)
- delete_Menuitem.keyEquivalent = "⌘ " + "⌫"
- menuItemArr.append(delete_Menuitem)
- viewHeight += 36.0
- }
-
- rightGroupView = groupView
- groupView?.groupDelegate = self
- groupView?.frame = CGRectMake(310, 0, 200, viewHeight)
- groupView?.updateGroupInfo(menuItemArr)
-
- var point = event.locationInWindow
- point.y = point.y - (groupView?.frame.size.height ?? 0)
- groupView?.showWithPoint(point, relativeTo: nil)
- }
-
- func showSearchGroupView(sender: ComponentButton) {
- var viewHeight: CGFloat = 8
- var menuItemArr: [ComponentMenuitemProperty] = []
- let titles = ["Whole Words","Case Sensitive"]
- for i in titles {
- let menuI = ComponentMenuitemProperty(text: KMLocalizedString(i))
- menuItemArr.append(menuI)
- viewHeight += 36
- }
-
- if let info = menuItemArr.first {
- if KMDataManager.ud_bool(forKey: KMNSearchKey.wholeWords.botaSearch) {
- info.righticon = NSImage(named: "KMNImageNameMenuSelect")
- }
- }
- if let info = menuItemArr.last {
- if KMDataManager.ud_bool(forKey: KMNSearchKey.caseSensitive.botaSearch) {
- info.righticon = NSImage(named: "KMNImageNameMenuSelect")
- }
- }
-
- let groupView = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
- searchGroupView = groupView
- groupView?.groupDelegate = self
- groupView?.frame = CGRectMake(310, 0, 200, viewHeight)
- groupView?.updateGroupInfo(menuItemArr)
-
- var point = sender.convert(sender.frame.origin, to: nil)
- point.y -= viewHeight
- groupView?.showWithPoint(point, relativeTo: sender)
- searchGroupTarget = sender
- }
-
- func displayNoteViewAnimating(_ animate: Bool) {
- searchViewController.contentView = nil
- if let data = noteOutlineView.enclosingScrollView {
- replaceSideView(data, animate: animate)
- }
-
- var frame = noteOutlineView.enclosingScrollView?.frame ?? .zero
- frame.origin.y = 0
- frame.size.height = noteOutlineView.enclosingScrollView?.superview?.frame.size.height ?? 0
- noteOutlineView.enclosingScrollView?.frame = frame
-
- reloadAnnotation()
- }
-
- func displayEmptyViewAnimating(_ animate: Bool) {
- leftListView.addSubview(emptyView)
- emptyView.km_add_top_constraint(constant: 232)
- emptyView.km_add_bottom_constraint()
- emptyView.km_add_leading_constraint()
- emptyView.km_add_trailing_constraint()
- emptyView.isHidden = true
- }
- }
- //MARK: Cache
- extension KMLeftSideViewController {
- func clearNotification() {}
- }
- // MARK: - Private Methods
- extension KMLeftSideViewController {
-
- func updateThumbnail(at index: Int) {
- var indexs = IndexSet()
- indexs.insert(index)
- self.delegate?.listViewThumPageIndeDidChange?(controller: self, pageIndexs: indexs)
- }
- }
- // MARK: - NSOutlineViewDelegate, NSOutlineViewDataSource
- extension KMLeftSideViewController: NSOutlineViewDelegate, NSOutlineViewDataSource {
- func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
- if outlineView.isEqual(to: noteOutlineView) {
- if self.noteSearchMode {
- var cnt = 0
- for model in noteSearchArray {
- cnt += 2
- guard let data = model as? KMBotaAnnotationModel else {
- continue
- }
- if data.isExpand == false {
- continue
- }
- for replyI in data.replyAnnos {
- cnt += 1
- }
- }
- return cnt
- }
- var cnt = 0
- for sectionM in annoListModel?.datas ?? [] {
- if sectionM.items.count > 0 {
- cnt += 1
- if sectionM.isExpand == false {
- continue
- }
- for item in sectionM.items {
- cnt += 1
- if let annoItem = item as? KMBotaAnnotationModel {
- if annoItem.isExpand == false {
- continue
- }
- for replyItem in annoItem.replyAnnos {
- cnt += 1
- }
- }
- }
- }
- }
-
- self.noteOutlineView.usesAlternatingRowBackgroundColors = false
- let hasAnno = self.allAnnotations.count >= 1
- if(!hasAnno) {
- headerView.sortButton.properties.isDisabled = true
- headerView.searchButton.properties.isDisabled = true
- } else {
- headerView.sortButton.properties.isDisabled = false
- headerView.searchButton.properties.isDisabled = false
- }
- headerView.sortButton.reloadData()
- headerView.searchButton.reloadData()
- headerView.moreButton.reloadData()
- if cnt < 1 {
- self.showNoteEmptyView()
- } else {
- self.hideNoteEmptyView()
- }
-
- return cnt
- }
- return 0
- }
-
- func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
- if outlineView.isEqual(to: self.noteOutlineView) {
- if self.noteSearchMode {
- var idx = 0
- var models: [KMBotaAnnotationBaseModel] = []
- for model in self.noteSearchArray {
- models.append(model)
- if let data = (model as? KMBotaAnnotationModel)?.footerModel {
- models.append(data)
- }
- }
- for model in models {
- idx += 1
- if index + 1 == idx {
- return model
- }
- guard let data = model as? KMBotaAnnotationModel else {
- continue
- }
- if data.isExpand == false {
- continue
- }
- for replyI in data.replyAnnos {
- idx += 1
- if index + 1 == idx {
- return replyI
- }
- }
- }
- return 0
- }
-
- var idx = 0
- var flagSectionM: KMBotaAnnotationSectionModel?
- var flagItem: KMBotaAnnotationBaseModel?
- var replyIten: KMBotaAnnotationReplyModel?
- var isSection = false
- var isReply = false
- for sectionM in self.annoListModel?.datas ?? [] {
- idx += 1
- if index + 1 == idx {
- flagSectionM = sectionM
- isSection = true
- break
- }
- if sectionM.isExpand == false {
- continue
- }
- for item in sectionM.items {
- idx += 1
- if index + 1 == idx {
- flagSectionM = sectionM
- flagItem = item
- break
- }
- guard let annoItem = item as? KMBotaAnnotationModel else {
- continue
- }
- if annoItem.isExpand == false {
- continue
- }
- for replyI in annoItem.replyAnnos {
- idx += 1
- if index + 1 == idx {
- flagSectionM = sectionM
- flagItem = item
- replyIten = replyI
- isReply = true
- break
- }
- }
- }
- }
- if isSection {
- return flagSectionM
- }
- if isReply {
- return replyIten
- }
- return flagItem
- }
- return item as Any
- }
-
- func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
- if outlineView.isEqual(to: noteOutlineView) {
- if let data = item as? KMBotaAnnotationSectionModel {
- var cell = outlineView.makeView(withIdentifier: KMAnnotationSectionCellView.km_identifier, owner: nil) as? KMAnnotationSectionCellView
- if cell == nil {
- cell = KMAnnotationSectionCellView.createFromNib()
- }
- cell?.isExpand = data.isExpand
- if self.noteSortType == .page {
- let pageIndex = data.items.first?.anno?.page.pageIndex() ?? 0
- cell?.titleLabel.stringValue = KMLocalizedString("Page") + " \(pageIndex + 1)"
- } else {
- if let date = data.items.first?.anno?.modificationDate() {
- let string = KMTools.timeString(timeDate: date, formatString: "yyyy-MM-dd")
- cell?.titleLabel.stringValue = string
- } else {
- cell?.titleLabel.stringValue = ""
- }
- }
- cell?.countLabel.stringValue = "\(data.itemCount / 2)"
-
- cell?.itemClick = {[weak self] idx, _ in
- if idx == 1 { // 收取 & 展开
- data.isExpand = !data.isExpand
-
- self?.noteOutlineView.reloadData()
- }
- }
- return cell
- }
- if let data = item as? KMBotaAnnotationFooterModel {
- var cell = outlineView.makeView(withIdentifier: KMNoteFooterCellView.km_identifier, owner: self) as? KMNoteFooterCellView
- if cell == nil {
- cell = KMNoteFooterCellView.createFromNib()
- }
- cell?.model = data
-
- let state = noteReplyHanddler.fetchReviewState(data.anno) ?? .none
- if state == .none {
- cell?.operationIv.image = NSImage(named: "KMNImageNameBotaNoteStateNone")
- } else if state == .completed {
- cell?.operationIv.image = NSImage(named: "KMNImageNameBotaNoteStateCompleted")
- } else if state == .canceled {
- cell?.operationIv.image = NSImage(named: "KMNImageNameBotaNoteStateCancelled")
- } else if state == .accepted {
- cell?.operationIv.image = NSImage(named: "KMNImageNameBotaNoteStateAccepted")
- } else if state == .rejected {
- cell?.operationIv.image = NSImage(named: "KMNImageNameBotaNoteStateRejected")
- }
- cell?.operationBox.toolTip = KMPDFAnnotationStateGetString(state: state)
-
- if let con = data.replyModel?.replyAnno?.contents, con.isEmpty == false {
- cell?.inputTextF.stringValue = con
- DispatchQueue.main.async {
- self.view.window?.makeFirstResponder(cell?.inputTextF)
- }
- } else if let con = data.editAnnoModel?.anno?.contents, con.isEmpty == false {
- cell?.inputTextF.stringValue = con
- DispatchQueue.main.async {
- self.view.window?.makeFirstResponder(cell?.inputTextF)
- }
- } else {
- if let cont = data.inputContent {
- cell?.inputTextF.stringValue = cont
- } else {
- cell?.inputTextF.stringValue = ""
- }
- }
-
- cell?.updateUI(expand: data.isExpand, animated: data.animated)
- data.animated = false
-
- if data.isFirstResp {
- DispatchQueue.main.async {
- self.view.window?.makeFirstResponder(cell?.inputTextF)
- }
- data.isFirstResp = false
- }
-
- cell?.inputDidChanged = { value, _ in
- data.inputContent = value as? String ?? ""
- }
-
- cell?.itemClick = { [weak self] idx, param in
- if idx == 1 { // comment
- data.isExpand = !data.isExpand
- data.animated = true
- data.isFirstResp = true
- self?.noteOutlineView.reloadItem(data)
- } else if idx == 2 { //
- self?.noteReplyHanddler.showStatePopView(sender: param.first as! NSView, anno: data.anno)
- } else if idx == 3 { // reply
- let content = param.first as? String ?? ""
- if content.isEmpty {
- return
- }
-
- if let con = data.replyModel?.replyAnno?.contents, con.isEmpty == false { // 编辑
- let model = data.replyModel
- model?.replyAnno?.contents = content
- model?.replyAnno?.setUserName(KMPreference.shared.author)
- model?.replyAnno?.setModificationDate(Date())
-
- // 置空编辑状态
- data.replyModel = nil
- data.inputContent = nil
- self?.noteOutlineView.reloadData()
- if let row = self?.noteOutlineView.row(forItem: data) {
- self?.noteOutlineView.scrollRowToVisible(row)
- }
- return
- }
-
- if let con = data.editAnnoModel?.anno?.contents, con.isEmpty == false { // 编辑
- let model = data.editAnnoModel
- model?.anno?.contents = content
- model?.anno?.setUserName(KMPreference.shared.author)
-
- // 置空编辑状态
- data.replyModel = nil
- data.inputContent = nil
- data.editAnnoModel = nil
- self?.noteOutlineView.reloadData()
- if let row = self?.noteOutlineView.row(forItem: data) {
- self?.noteOutlineView.scrollRowToVisible(row)
- }
- return
- }
- if let replyAnno = self?.noteReplyHanddler.createReplyAnnotation(data.anno, content: content, userName: KMPreference.shared.author) {
- let model = KMBotaAnnotationReplyModel()
- model.anno = data.anno
- model.replyAnno = replyAnno
- model.annoModel = data.annoModel
- data.annoModel?.replyAnnos.append(model)
- data.inputContent = nil
- self?.noteOutlineView.reloadData()
- if let row = self?.noteOutlineView.row(forItem: data) {
- self?.noteOutlineView.scrollRowToVisible(row)
- }
- }
- } else if idx == 4 { // cancel
- data.isExpand = false
- data.replyModel = nil
- data.inputContent = nil
- self?.noteOutlineView.reloadItem(data)
- }
- }
-
- return cell
- }
- if let data = item as? KMBotaAnnotationReplyModel {
- var cell = outlineView.makeView(withIdentifier: KMNoteReplyCellView.km_identifier, owner: self) as? KMNoteReplyCellView
- if cell == nil {
- cell = KMNoteReplyCellView.createFromNib()
- }
- cell?.model = data
- cell?.titleLabel.stringValue = data.replyAnno?.userName() ?? ""
- if let data = data.replyAnno?.modificationDate() {
- cell?.timeLabel.stringValue = KMTools.timeString(timeDate: data)
- } else {
- cell?.timeLabel.stringValue = ""
- }
- cell?.contentLabel.stringValue = data.replyAnno?.contents ?? ""
- cell?.itemClick = { [weak self] idx, params in
- if idx == 1 { // 更多
- self?.noteReplyHanddler.showReplyMorePopView(sender: params.first as! NSView, replyModel: data)
- }
- }
- return cell
- }
-
- if let data = item as? KMBotaAnnotationModel {
- let note = (item as? KMBotaAnnotationModel)?.anno
- var cell = outlineView.makeView(withIdentifier: KMNoteTableViewCell.km_identifier, owner: self) as? KMNoteTableViewCell
- if cell == nil {
- cell = KMNoteTableViewCell.createFromNib()
- }
-
- cell?.cellNote = note
- cell?.model = data
- let state = self.noteReplyHanddler.fetchAnnoState(note) ?? .unMarked
- cell?.state = state
- cell?.itemClick = { [weak self] idx , _ in
- if idx == 1 { // Markup
- self?.updateMarkState(model: data)
- }
- }
- cell?.isUnFoldNote = { [weak self] cellNote, isUnfold in
- self?.updateExpand(model: data, isExpand: isUnfold, item: item)
- }
- return cell
- }
- }
- return nil
- }
-
- func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
- if outlineView.isEqual(self.noteOutlineView) {
- if let model = item as? KMBotaAnnotationModel {
- if model.isExpand == false {
- return model.foldH
- }
- if let anno = model.anno {
- return KMBOTAAnnotationTool.fetchCellHeight(annotation: anno, maxSize: CGSize(width: 260+40 - 16, height: 1000))
- }
- }
- return 40
- }
- return outlineView.rowHeight
- }
-
- func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
- if outlineView.isEqual(to: self.noteOutlineView) {
- return false
- }
- return false
- }
-
- func outlineView(_ outlineView: NSOutlineView, rowViewForItem item: Any) -> NSTableRowView? {
- if outlineView.isEqual(self.noteOutlineView) {
- let itemView = KMBotaTableRowView()
- if let data = item as? KMBotaAnnotationBaseModel {
- itemView.isSelected = data.isSelected
- }
- let rowIndexes = self.noteOutlineView.selectedRowIndexes
- itemView.rightMouseCallback = { [weak self] (view, event) in
- if let data = item as? KMBotaAnnotationFooterModel {
-
- } else {
- if !KMOCToolClass.arrayContains(array: self?.selectedObjcNotes(), annotation: item) ||
- self?.selectedObjcNotes().count == 1 {
- let index = self?.noteOutlineView.row(forItem: item)
- self?.noteOutlineView.selectRowIndexes(IndexSet(integer: IndexSet.Element(index ?? 0)), byExtendingSelection: false)
- }
-
- let row = outlineView.row(forItem: item)
- if outlineView.rowView(atRow: row, makeIfNecessary: false) != nil {
- let rowView = outlineView.rowView(atRow: row, makeIfNecessary: false)
- self?.showRightGropView(raw: row, event: event, view: rowView,item: item)
- }
- }
- }
-
- itemView.selectCallback = { theView in
- let isSelected = theView.isSelected
-
- if theView.numberOfColumns > 0 {
- let cellView = theView.view(atColumn: 0)
- if let data = cellView as? KMAnnotationSectionCellView {
- return
- }
- var model: KMBotaAnnotationModel?
- var indexs = IndexSet()
- if let data = cellView as? KMNoteFooterCellView {
- model = data.model?.annoModel
- model?.isSelected = isSelected
-
- self.view.window?.makeFirstResponder(data.inputTextF)
- }
- if let data = cellView as? KMNoteReplyCellView {
- model = data.model?.annoModel
-
- model?.isSelected = isSelected
- }
- if let data = cellView as? KMNoteTableViewCell {
- model = data.model
- model?.isSelected = isSelected
- }
- if let data = model {
- let row = self.noteOutlineView.row(forItem: data)
- indexs.insert(row)
- var i = 1
- for item in model?.replyAnnos ?? [] {
- indexs.insert(row+i)
- i += 1
- }
- indexs.insert(row+i)
- }
- }
-
- }
- return itemView;
- }
- return nil
- }
-
- func outlineView(_ outlineView: NSOutlineView, selectionIndexesForProposedSelection proposedSelectionIndexes: IndexSet) -> IndexSet {
- if outlineView.isEqual(to: self.noteOutlineView) {
- for i in proposedSelectionIndexes {
- let item = self.noteOutlineView.item(atRow: i)
- if let data = item as? KMBotaAnnotationFooterModel {
- return IndexSet()
- }
- }
- }
- return proposedSelectionIndexes
- }
-
- func outlineViewSelectionDidChange(_ notification: Notification) {
- let selectedNotes = self.selectedNotes()
- if selectedNotes.count == 1 {
- let annotation = selectedNotes.last!
- self.listView?.go(to: annotation.bounds, on: annotation.page, animated: true)
- if self.hideNotes() == false {
- self.listView?.updateActiveAnnotations([annotation])
- self.listView?.setNeedsDisplayAnnotationViewForVisiblePages()
- if annotation is CPDFPolygonAnnotation || annotation is CPDFPolylineAnnotation {
- self.listView?.pdfListViewDelegate.pdfListViewAnnotationMeasureInfoChange?(self.listView, with: annotation)
- } else if let anno = annotation as? CPDFLineAnnotation {
- if anno.isMeasure {
- self.listView?.pdfListViewDelegate.pdfListViewAnnotationMeasureInfoChange?(self.listView, with: annotation)
- }
- }
- }
- } else if(selectedNotes.count > 1){
- let lastSelectedNote = selectedNotes.last!
- let firstSelectedNote = selectedNotes.first!
- self.listView?.go(to: lastSelectedNote.bounds, on: lastSelectedNote.page, animated: true)
- if self.hideNotes() == false {
- if lastSelectedNote.page == firstSelectedNote.page {//同页的话支持多选选中
- var activeAnnotations:[CPDFAnnotation] = listView?.activeAnnotations as! [CPDFAnnotation]
- activeAnnotations.append(lastSelectedNote)
- self.listView?.updateActiveAnnotations(activeAnnotations)
- } else {
- self.listView?.updateActiveAnnotations([lastSelectedNote])
- let rowIndexes = self.noteOutlineView.selectedRowIndexes
-
- for i in 0 ..< rowIndexes.count - 1 {
- noteOutlineView.deselectRow(i)
- }
- }
- self.listView?.setNeedsDisplayAnnotationViewForVisiblePages()
- if lastSelectedNote is CPDFPolygonAnnotation || lastSelectedNote is CPDFPolylineAnnotation {
- self.listView?.pdfListViewDelegate.pdfListViewAnnotationMeasureInfoChange?(self.listView, with: lastSelectedNote)
- } else if let anno = lastSelectedNote as? CPDFLineAnnotation {
- if anno.isMeasure {
- self.listView?.pdfListViewDelegate.pdfListViewAnnotationMeasureInfoChange?(self.listView, with: lastSelectedNote)
- }
- }
- }
- }
- }
-
- func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
- var dragOp = NSDragOperation(rawValue: 0)
- if outlineView.isEqual(to: self.noteOutlineView) {
- let pboard = info.draggingPasteboard
- if pboard.canReadObject(forClasses: [NSColor.self], options: [:]) && index == NSOutlineViewDropOnItemIndex {
- if let note = item as? CPDFAnnotation, note.type != nil {
- dragOp = .every
- }
- }
- }
- return dragOp
- }
-
- func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
- if outlineView.isEqual(to: noteOutlineView) {
- let pboard = info.draggingPasteboard
- if pboard.canReadObject(forClasses: [NSColor.self], options: [:]) {
- let isShift = NSEvent.modifierFlags.contains(.shift)
- let isAlt = NSEvent.modifierFlags.contains(.option)
- guard let note = item as? CPDFAnnotation else {
- NSSound.beep()
- return false
- }
- if let color = NSColor(from: pboard) {
- note.setColor(color, alternate: isAlt, updateDefaults: isShift)
- return true
- }
- return false
- }
- }
- return false
- }
- func outlineView(_ outlineView: NSOutlineView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, byItem item: Any?) {
- if outlineView.isEqual(to: noteOutlineView) {
- var note: CPDFAnnotation?
- if let data = item as? CPDFAnnotation {
- note = data
- } else if let data = item as? KMBotaAnnotationModel {
- note = data.anno
- }
- if let data = note?.type, data.isEmpty == false {
- if tableColumn?.identifier.rawValue == self.noteColumnId.rawValue {
- let string1 = (object as? String) ?? ""
- let string2 = note?.string() ?? ""
- if string1 != string2 {
- note?.setString(string1)
- }
- } else if tableColumn?.identifier.rawValue == self.authorColumnId.rawValue {
- let string1 = (object as? String) ?? ""
- let string2 = note?.userName() ?? ""
- if string1 != string2 {
- note?.setUserName(string1)
- }
- }
- }
- }
- }
-
- func outlineView(_ outlineView: NSOutlineView, dataCellFor tableColumn: NSTableColumn?, item: Any) -> NSCell? {
- if noteOutlineView.isEqual(to: outlineView) {
- if tableColumn == nil {
- if let anno = item as? CPDFAnnotation, anno.type == nil {
- return outlineView.tableColumn(withIdentifier: self.noteColumnId)?.dataCell(forRow: outlineView.row(forItem: item)) as? NSCell
- }
- }
- }
- return tableColumn?.dataCell(forRow: outlineView.row(forItem: item)) as? NSCell
- }
-
- func outlineView(_ outlineView: NSOutlineView, shouldEdit tableColumn: NSTableColumn?, item: Any) -> Bool {
- if outlineView.isEqual(to: noteOutlineView) {
- if (tableColumn == nil) {
- if self.hideNotes() == false {
- if let anno = item as? CPDFAnnotation, anno.isNote() {
- self.listView?.scrollAnnotationToVisible(anno)
- self.listView?.updateActiveAnnotations([anno])
- }
- }
- return false
- } else if tableColumn?.identifier.rawValue == self.noteColumnId.rawValue || tableColumn?.identifier.rawValue == self.authorColumnId.rawValue {
- return true
- }
- }
- return false
- }
-
- func outlineView(_ outlineView: NSOutlineView, toolTipFor cell: NSCell, rect: NSRectPointer, tableColumn: NSTableColumn?, item: Any, mouseLocation: NSPoint) -> String {
- if outlineView.isEqual(to: self.noteOutlineView) {
- if tableColumn == nil || tableColumn?.identifier.rawValue == self.noteColumnId.rawValue {
- return (item as? CPDFAnnotation)?.string() ?? ""
- }
- }
- return ""
- }
-
- func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItems draggedItems: [Any]) {
- self.dragIn = true
- }
-
- func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) {
- self.dragIn = false
- }
-
- func noteItems(_ items: NSArray) -> NSArray {
- let noteItems = NSMutableArray()
-
- for item in items {
- guard let anno = (item as? KMBotaAnnotationModel)?.anno else {
- continue
- }
- if anno.type == nil {
- }
- if noteItems.contains(anno) == false {
- noteItems.add(anno)
- }
- }
- return noteItems
- }
- }
- // MARK: - KMCustomOutlineViewDelegate, KMCustomOutlineViewDataSource
- extension KMLeftSideViewController: KMCustomOutlineViewDelegate, KMCustomOutlineViewDataSource {
- func outlineView(_ anOutlineView: NSOutlineView, canDeleteItems items: [Any]) -> Bool {
- if anOutlineView.isEqual(to: noteOutlineView) {
- return self.hideNotes() == false && items.count > 0
- }
- return false
- }
-
- func outlineView(_ anOutlineView: NSOutlineView, deleteItems items: [Any]) {
- if anOutlineView.isEqual(to: noteOutlineView) {
- if (items.isEmpty) {
- return
- }
- self.dataUpdating = true
- for item in self.noteItems(items as NSArray) {
- guard let anno = item as? CPDFAnnotation else {
- continue
- }
- if let data = anno as? CPDFFreeTextAnnotation {
- self.listView?.commitEditAnnotationFreeText(data)
- }
- self.listView?.remove(anno)
- }
- for item in items {
- if let data = item as? KMBotaAnnotationModel {
- data.sectionModel?.items.removeObject(data)
- if let footerModel = data.footerModel {
- data.sectionModel?.items.removeObject(footerModel)
- }
- }
- }
- self.dataUpdating = false
- self.listView?.undoManager?.setActionName(KMLocalizedString("Remove Note", comment: "Undo action name"))
-
- self.note_refrshUIIfNeed()
- }
- }
- func outlineView(_ anOutlineView: NSOutlineView, canCopyItems items: [Any]) -> Bool {
- if anOutlineView.isEqual(to: noteOutlineView) {
- if (items.count == 1) {
- }
- return items.count > 0
- }
- return false
- }
-
- func outlineView(_ anOutlineView: NSOutlineView, copyItems items: [Any]) {
- if anOutlineView.isEqual(to: self.noteOutlineView) && items.isEmpty == false {
- }
- }
- func outlineView(_ anOutlineView: NSOutlineView, typeSelectHelperSelectionStrings aTypeSelectHelper: SKTypeSelectHelper) -> NSArray {
- if noteOutlineView.isEqual(to: anOutlineView) {
- let count = self.noteOutlineView.numberOfRows
- let texts = NSMutableArray(capacity: count)
- for i in 0 ..< count {
- let item = self.noteOutlineView.item(atRow: i)
- let string = (item as? CPDFAnnotation)?.string() ?? ""
- texts.add(string)
- }
- return texts
- }
- return []
- }
- }
- // MARK: - Other
- extension KMLeftSideViewController {
-
- func fileNameWithSelectedPages(_ itemIndexes: IndexSet) -> String {
- var pagesName = ""
- if (itemIndexes.count > 1) {
- pagesName.append(" pages")
- } else {
- pagesName.append(" page")
- }
-
- let docmentName = self.pdfDocument()?.documentURL.deletingPathExtension().lastPathComponent ?? ""
- let tFileName = String(format: "%@ %@", pagesName,KMTools.parseIndexSet(indexSet: itemIndexes))
- return String(format: "%@%@", docmentName,tFileName)
- }
-
- func draggedFileName(for page: CPDFPage) -> String {
- let pageIndex = "\(page.pageIndex() + 1)"
- var fileName = ""
- if let doc = self.view.window?.windowController?.document as? NSDocument {
- fileName = doc.fileURL?.deletingPathExtension().lastPathComponent ?? (MainBundle.nameSpaceName ?? "")
- }
- return "\(fileName)-Page \(pageIndex)"
- }
-
-
- func updateTableFont() {
- }
- }
- // MARK: - ComponentGroupDelegate
- extension KMLeftSideViewController: ComponentGroupDelegate {
- func componentGroupDidDismiss(group: ComponentGroup?) {
- if group == searchGroupView {
- searchGroupTarget?.properties.state = .normal
- searchGroupTarget?.reloadData()
- searchGroupTarget = nil
- } else if group == moreGroupView {
- headerView.moreButton.properties.state = .normal
- headerView.moreButton.reloadData()
- }
- }
-
- func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) {
-
- if group == searchGroupView {
- guard let menuI = menuItemProperty else {
- return
- }
- let idx = group?.menuItemArr.firstIndex(of: menuI)
- if idx == 0 {
- let key = KMNSearchKey.wholeWords.botaSearch
- let value = KMDataManager.ud_bool(forKey: key)
- KMDataManager.ud_set(!value, forKey: key)
- } else if idx == 1 {
- let key = KMNSearchKey.caseSensitive.botaSearch
- let value = KMDataManager.ud_bool(forKey: key)
- KMDataManager.ud_set(!value, forKey: key)
- }
- } else {
- if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_Expand {
- var isExpandAllItem = true
- for secM in self.annoListModel?.datas ?? [] {
- if secM.isExpand == false {
- isExpandAllItem = false
- break
- }
- }
- if isExpandAllItem == true {
- note_foldAllComments(nil)
- } else {
- note_expandAllComments(nil)
- }
- } else if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_SortPage {
- self.noteSortType = .page
- if let data = self.listView?.document?.documentURL.path {
- KMDataManager.udExtension_set(self.noteSortType.rawValue, forKey: Self.Key.noteSortTypeKey + data)
- }
-
- if self.noteSearchMode {
- self.reloadNoteForSearchMode()
- } else {
- self.reloadAnnotation()
- }
- } else if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_SortAscTime {
- self.noteSortType = .time
- self.isAscendSort = true
- if let data = self.listView?.document?.documentURL.path {
- KMDataManager.udExtension_set(self.noteSortType.rawValue, forKey: Self.Key.noteSortTypeKey + data)
- }
-
- if self.noteSearchMode {
- self.reloadNoteForSearchMode()
- } else {
- self.reloadAnnotation()
- }
- } else if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_SortDesTime {
- self.noteSortType = .time
- self.isAscendSort = false
- if let data = self.listView?.document?.documentURL.path {
- KMDataManager.udExtension_set(self.noteSortType.rawValue, forKey: Self.Key.noteSortTypeKey + data)
- }
-
- if self.noteSearchMode {
- self.reloadNoteForSearchMode()
- } else {
- self.reloadAnnotation()
- }
- } else if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_Improt {
- importNotes(nil)
- } else if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_Export {
- exportNotes(nil)
- } else if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_RemoveAll {
- removeAllAnnotations(nil)
- } else if menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_DeleteRep {
- removeAllReplyAnnotations(nil)
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_EditNote) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- let model = models.first
- if model != nil {
- updateExpand(model: model!, isExpand: true, item: currentItem)
- noteReplyHanddler.editAnnotation(annotationModel: model!)
- DispatchQueue.main.async {
- let row = self.noteOutlineView.row(forItem: model?.footerModel)
- self.noteOutlineView.scrollRowToVisible(row)
- }
- self.noteOutlineView.reloadData()
- }
- }
- } else if let anModels = menuItemProperty?.representedObject as? [KMBotaAnnotationReplyModel] {
- if anModels.first != nil {
- let model = anModels.first
- noteReplyHanddler.editReplyAnnotation(replyModel: model)
- DispatchQueue.main.async {
- let row = self.noteOutlineView.row(forItem: model?.annoModel?.footerModel)
- self.noteOutlineView.scrollRowToVisible(row)
- }
- self.noteOutlineView.reloadData()
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_AddRep) {
- if let anModels = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if anModels.first != nil {
- if let model = anModels.first {
- self.updateExpand(model: model, isExpand: true, item: currentItem)
- if let footMode = model.footerModel {
- let row = self.noteOutlineView.row(forItem: footMode)
- let rowView = self.noteOutlineView.rowView(atRow: row, makeIfNecessary: true)
- if(row != nil) {
- for subview in rowView!.subviews {
- if let cell = subview as? KMNoteFooterCellView {
- cell.inputTextF.becomeFirstResponder()
- }
- }
- }
- }
- }
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_AddMark) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- updateMarkState(model: models.first!)
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_RepStateNone) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- updateReplaState(model:models.first! , state:.none)
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_RepStateAccepted) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- updateReplaState(model:models.first! , state:.accepted)
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_RepStateRejected) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- updateReplaState(model:models.first! , state:.rejected)
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_RepStateCancelled) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- updateReplaState(model:models.first! , state:.canceled)
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_RepStateCompleted) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- updateReplaState(model:models.first! , state:.completed)
- }
- }
- } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ShowPopUI) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- let model = models.first
- updateExpand(model: model!, isExpand: !(model?.isExpand == true), item: currentItem)
- }
- } else if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationReplyModel] {
- if models.first != nil {
- let model = models.first
- let anModel = model?.annoModel
- if anModel != nil {
- updateExpand(model: anModel!, isExpand: false, item: currentItem)
- }
- }
- }
- } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Copy) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- let model = models.first
- let an = model?.anno
- var copyText:String = ""
- if an?.isKind(of: CPDFMarkupAnnotation.self) == true {
- if let markupAn = an as? CPDFMarkupAnnotation {
- copyText = markupAn.markupContent()
- }
- } else if an?.isKind(of: CPDFFreeTextAnnotation.self) == true ||
- an?.isKind(of: CPDFTextAnnotation.self) == true {
- copyText = an?.contents ?? ""
- }
- let pboard = NSPasteboard.general
- if copyText.isEmpty == false {
- pboard.clearContents()
- pboard.writeObjects([copyText as NSPasteboardWriting])
- }
- }
- }
- } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Delete) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationModel] {
- if models.first != nil {
- let model = models.first
- self.outlineView(self.noteOutlineView, deleteItems:[model!])
- }
- }
- } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_CopyText) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationReplyModel] {
- if models.first != nil {
- let model = models.first
-
- var copyText:String = ""
- copyText = model?.replyAnno?.contents ?? ""
- let pboard = NSPasteboard.general
- if copyText.isEmpty == false {
- pboard.clearContents()
- pboard.writeObjects([copyText as NSPasteboardWriting])
- }
- }
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_DeleteMuteRep) {
- if let models = menuItemProperty?.representedObject as? [Any] {
- for i in 0 ..< models.count {
- let model = models[i]
- if let replyModel = model as? KMBotaAnnotationReplyModel {
- noteReplyHanddler.removeReplyAnnotation(replyModel.replyAnno)
- replyModel.annoModel?.replyAnnos.removeObject(replyModel)
- } else if let anModel = model as? KMBotaAnnotationModel {
- self.outlineView(self.noteOutlineView, deleteItems:[anModel])
- }
- }
- self.noteOutlineView.reloadData()
- }
- } else if (menuItemProperty?.identifier == BOTAMenuIdentifier_Annotation_DeleteSignRep) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationReplyModel] {
- if models.first != nil {
- let model = models.first
- if model != nil {
- noteReplyHanddler.removeReplyAnnotation(model?.replyAnno)
- model?.annoModel?.replyAnnos.removeObject(model!)
- }
- self.noteOutlineView.reloadData()
- }
- }
- }
- }
- }
- }
|