12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664 |
- //
- // 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 moreButtonLayer: KMButtonLayer?
-
- // 注释
- 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.titleLabel.textColor = KMNColorTools.colorText_2()
- 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.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("Expand All")
- for secM in self.annoListModel?.datas ?? [] {
- if secM.isExpand == false {
- expand_MenuString = KMLocalizedString("Collapse All")
- break
- }
- }
-
- let expand_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(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(text: KMLocalizedString("By Page"),identifier: BOTAMenuIdentifier_Annotation_SortPage)
- let timeAscProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("By Time - Ascending"),identifier: BOTAMenuIdentifier_Annotation_SortAscTime)
- let timeDecProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(
- 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(text: KMLocalizedString("Import Annotations"),
- identifier: BOTAMenuIdentifier_Annotation_Improt)
-
- let rem_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(text: KMLocalizedString("Remove All Annotations"),
- identifier: BOTAMenuIdentifier_Annotation_RemoveAll)
- let delete_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(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("Notes"),
- 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("Notes"),
- identifier: BOTAMenuIdentifier_Annotation_EditNote,representedObject: [replyModel])
- menuItemArr.append(note_Menuitem)
- viewHeight += 36.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 = NSPoint(x: CGRectGetMaxX(view?.frame ?? CGRectZero), y: CGRectGetMidY(view?.frame ?? CGRectZero))
- point = noteOutlineView.convert(point, to: nil)
- point.y -= (groupView?.frame.size.height ?? 0)/2
- groupView?.showWithPoint(point, relativeTo: view)
- }
-
- 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.annotation) {
- info.righticon = NSImage(named: "KMNImageNameMenuSelect")
- }
- }
- if let info = menuItemArr.last {
- if KMDataManager.ud_bool(forKey: KMNSearchKey.caseSensitive.annotation) {
- 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
- headerView.moreButton.properties.isDisabled = true
- } else {
- headerView.sortButton.properties.isDisabled = false
- headerView.searchButton.properties.isDisabled = false
- headerView.moreButton.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
- }
- let model = item as? KMBotaAnnotationModel
- let note = (item as? KMBotaAnnotationModel)?.anno
- let cell = outlineView.makeView(withIdentifier: KMNoteTableViewCell.km_identifier, owner: self) as! KMNoteTableViewCell
- cell.cellNote = note
- cell.model = model
- let state = self.noteReplyHanddler.fetchAnnoState(note) ?? .unMarked
- cell.state = state
- if let data = note {
- if data.isKind(of: CPDFStampAnnotation.self) &&
- data.isKind(of: CSelfSignAnnotation.self) == false {
-
- } else {
- if data.isKind(of: CPDFMarkupAnnotation.self) {
- if (!cell.isFold) {
- } else {
- cell.imageViewHeightConstraint.constant = 18.0 + 8
- }
- } else {
- cell.imageViewHeightConstraint.constant = 18.0 + 8
- }
- }
- }
- cell.itemClick = { [weak self] idx , _ in
- if idx == 1 { // Markup
- if model != nil {
- self?.updateMarkState(model: model!)
- }
- }
- }
- cell.isUnFoldNote = { [weak self] cellNote, isUnfold in
- if model != nil {
- self?.updateExpand(model: model!, 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 30
- }
- 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) {
- if self.hideNotes() == false {
- let selectedNotes = self.selectedNotes()
- if selectedNotes.count == 1 {
- let annotation = selectedNotes.last!
- self.listView?.go(to: annotation.bounds, on: annotation.page, animated: true)
-
- 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 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.annotation
- let value = KMDataManager.ud_bool(forKey: key)
- KMDataManager.ud_set(!value, forKey: key)
- } else if idx == 1 {
- let key = KMNSearchKey.caseSensitive.annotation
- 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 (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Copy) {
- if let models = menuItemProperty?.representedObject as? [KMBotaAnnotationReplyModel] {
- 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()
- }
- }
- }
- }
- }
- }
|