123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- //
- // KMNoteTableViewCell.swift
- // PDF Reader Pro
- //
- // Created by tangchao on 2023/11/17.
- //
- import Cocoa
- import KMComponentLibrary
- class KMNoteTableViewCell: NSTableCellView {
- @IBOutlet var topView: NSView!
- @IBOutlet var typeImageView: NSImageView!
- @IBOutlet var autherLabel: NSTextField!
- @IBOutlet var timeLabel: NSTextField!
- @IBOutlet var pageLabel: NSTextField!
-
- @IBOutlet var contentView: NSView!
- @IBOutlet var foldButton: NSButton!
- @IBOutlet var annotationContentLabel: NSTextField!
- @IBOutlet var noteContentBox: NSBox!
- @IBOutlet var noteContentLabel: NSTextField!
- @IBOutlet var noteImageView: NSImageView!
-
- @IBOutlet var markupButton: KMCoverButton!
-
- @IBOutlet var topViewLayoutConstraint: NSLayoutConstraint!
- @IBOutlet var autherLayoutConstraint: NSLayoutConstraint!
- @IBOutlet var typeImageViewLayoutConstraint: NSLayoutConstraint!
- @IBOutlet var contentBoxLayoutConstraint: NSLayoutConstraint!
-
- @IBOutlet var maltlineLabelLayoutConstraint: NSLayoutConstraint!
- @IBOutlet var imageViewHeightConstraint: NSLayoutConstraint!
- @IBOutlet var pageLabelWidthConstraint: NSLayoutConstraint!
- @IBOutlet var noteContentHeightConstraint: NSLayoutConstraint!
-
- @IBOutlet var contentViewTopConstraint: NSLayoutConstraint!
- @IBOutlet var pageLabelTopConstraint: NSLayoutConstraint!
-
- @IBOutlet var timeWidthConstraint: NSLayoutConstraint!
- @IBOutlet var annotationContentWidthConstraint: NSLayoutConstraint!
-
- var state: CPDFAnnotationState = .unMarked {
- didSet {
- if self.state == .unMarked {
- self.markupButton.image = NSImage(named: "KMNImageNameBotaNoteMarkup")
- } else {
- self.markupButton.image = NSImage(named: "KMNImageNameBotaNoteMarkSelected")
- }
- }
- }
-
- var isFold = false {
- didSet {
- if (self.isFold) {
- self.maltlineLabelLayoutConstraint.constant = 18.0
-
- self.foldButton.image = NSImage(named: "KMImageNameBtnTriRightNor")
- self.noteContentBox.isHidden = true
-
- self.imageViewHeightConstraint.constant = 18.0 + 8
- } else {
- let labelheight = self._heightForNoteStringValue(self.annotationContentLabel.stringValue, maxW: NSWidth(self.annotationContentLabel.bounds))
- self.maltlineLabelLayoutConstraint.constant = labelheight + 18.0
-
- self.foldButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
-
- self.noteContentBox.isHidden = false
- let noteLabelHeight = self._heightForNoteStringValue(self.noteContentLabel.stringValue, maxW: NSWidth(self.noteContentLabel.bounds))
- self.noteContentHeightConstraint.constant = noteLabelHeight
-
- self.imageViewHeightConstraint.constant = self.maltlineLabelLayoutConstraint.constant + self.noteContentHeightConstraint.constant + 25
- }
- self.contentBoxLayoutConstraint.constant = self.noteContentBox.isHidden ? -(self.noteContentBox.bounds.size.height+8.0) : 8.0
- }
- }
- weak var cellNote: CPDFAnnotation?
- var isUnFoldNote: ((_ cellNote: CPDFAnnotation?, _ isUnfold: Bool)->Void)?
- var renameActionCallback: ((_ count: String)->Void)?
-
- var itemClick: KMCommonClickBlock?
-
- var model: KMBotaAnnotationModel? {
- didSet {
- self.updateView(self.model)
- }
- }
-
- override func draw(_ dirtyRect: NSRect) {
- super.draw(dirtyRect)
- // Drawing code here.
- }
-
- deinit {
- NotificationCenter.default.removeObserver(self)
- }
-
- override func awakeFromNib() {
- super.awakeFromNib()
-
- self.wantsLayer = true
- self.layer?.backgroundColor = .clear
- self.layer?.cornerRadius = 0.0
-
- self.autherLabel.wantsLayer = true
- self.autherLabel.layer?.backgroundColor = KMAppearance.Else.textTagColor().cgColor
- self.autherLabel.layer?.cornerRadius = 1.0
- self.autherLabel.textColor = KMAppearance.Layout.h0Color()
-
- self.timeLabel.lineBreakMode = .byTruncatingTail
- self.timeLabel.cell?.truncatesLastVisibleLine = true
- self.pageLabel.textColor = KMAppearance.Layout.h2Color()
-
- self.noteContentLabel.isEditable = false
- self.noteContentBox.borderWidth = 1.0
- self.noteContentBox.borderColor = KMAppearance.Layout.b15Color()
- self.noteContentBox.cornerRadius = 1.0
- self.noteContentBox.fillColor = KMAppearance.Layout.l1Color()
-
-
- self.annotationContentLabel.cell?.truncatesLastVisibleLine = true
- self.annotationContentLabel.isEditable = false
-
- self.markupButton.toolTip = KMLocalizedString("Add or Remove Marked")
- self.markupButton.target = self
- self.markupButton.action = #selector(markupAction)
- self.markupButton.coverAction = { [weak self] btn, act in
- let state = self?.state ?? .unMarked
- if state == .unMarked {
- btn.image = NSImage(named: "KMNImageNameBotaNoteMarkup")
- } else {
- btn.image = NSImage(named: "KMNImageNameBotaNoteMarkSelected")
- }
- }
-
- NotificationCenter.default.addObserver(self, selector: #selector(_contextDidEndEdit), name: NSControl.textDidEndEditingNotification, object: self.annotationContentLabel)
-
-
- self.isFold = true
-
- NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: APPAppearanceChangedNotificationName, object: nil)
- updateUI()
- }
-
- @objc func updateUI() {
- self.timeLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/3")
- self.noteContentLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
- self.annotationContentLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
-
- self.timeLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-xs-regular")
- self.noteContentLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-regular")
- self.annotationContentLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-regular")
- }
-
- func contentViewHidden(_ hidden: Bool) {
- self.contentViewTopConstraint.constant = hidden ? -(NSHeight(self.topView.bounds)) : 8.0
- self.pageLabelTopConstraint.constant = -(NSHeight(self.topView.bounds)-4)
- }
-
- @IBAction func foldButtonAction(_ sender: NSButton) {
- let anno = self.model?.anno
- if anno is CPDFStampAnnotation || anno is CPDFInkAnnotation || anno is CPDFSignatureAnnotation || anno is CPDFTextAnnotation {
- let expand = model?.isExpand ?? false
- if expand {
- self.foldButton.image = NSImage(named: "KMImageNameBtnTriRightNor")
- } else {
- self.foldButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
- }
- if (self.isUnFoldNote != nil) {
- self.isUnFoldNote!(self.cellNote, !expand)
- }
- } else {
- self.isFold = !self.isFold
-
- if (self.isUnFoldNote != nil) {
- self.isUnFoldNote!(self.cellNote, !self.isFold)
- }
- }
- }
-
- override func layout() {
- super.layout()
-
- let showAuthor = self.model?.showAuthor ?? false
- let authorW = showAuthor ? self.autherLabel.frame.size.width : 0
-
- let showTime = self.model?.showTime ?? false
- if showTime {
- let x: CGFloat = 16 + 10 + authorW
- let width = NSWidth(self.topView.frame)
- self.timeWidthConstraint.constant = width - x
- }
-
- let foldW: CGFloat = 16
- let contentW = NSWidth(self.contentView.frame)
- self.annotationContentWidthConstraint.constant = contentW-foldW
- }
-
- @objc func markupAction() {
- self.itemClick?(1)
- }
-
- }
- // MARK: - Private Methods
- extension KMNoteTableViewCell {
- @objc private func _contextDidEndEdit(_ notification: NSNotification) {
- let textField = notification.object as? NSTextField
- if self.noteContentLabel.isEqual(to: textField) {
- if (self.renameActionCallback != nil) {
- self.renameActionCallback!(textField!.stringValue)
- }
- }
- }
-
- private func _equalToImage(_ image: NSImage?) -> Bool {
- guard let _image = image else {
- return false
- }
-
- let imageData1 = _image.tiffRepresentation
- let imageData2 = NSImage(named: "KMImageNameBtnTriRightNor")?.tiffRepresentation
-
- return imageData1 == imageData2
- }
-
- private func _heightForNoteStringValue(_ text: String, maxW: CGFloat) -> CGFloat {
- let maxSize = NSMakeSize(maxW, CGFloat(MAXFLOAT))
- let opts: NSString.DrawingOptions = [.usesLineFragmentOrigin, .usesFontLeading]
- let style = NSMutableParagraphStyle()
- style.lineBreakMode = .byWordWrapping
-
- let attributes: [NSAttributedString.Key : Any] = [.font : NSFont.systemFont(ofSize: 14), .paragraphStyle : style]
- let rect = text.boundingRect(with: maxSize, options: opts, attributes: attributes)
-
- return rect.size.height
- }
-
- private func updateView(_ model: KMBotaAnnotationModel?) {
- let note = model?.anno
- let noteColor = note?.color
- let noteType = KMPDFAnnotationNoteType(note)
- var noteString = ""
- if let data = note {
- noteString = KMBOTAAnnotationTool.fetchContentLabelString(annotation: data)
- }
- let pageString = "\((note?.page?.pageIndex() ?? 0) + 1)"
- var dateString = ""
- if let date = note?.modificationDate() {
- dateString = KMTools.timeString(timeDate: date)
- }
- let authorString = note?.userName() ?? ""
- let noteTextString = note?.string() ?? ""
- let showTime = model?.showTime ?? true
- if showTime {
- self.timeLabel.stringValue = dateString
- self.timeLabel.lineBreakMode = .byTruncatingTail
- self.timeLabel.cell?.truncatesLastVisibleLine = true
- self.timeLabel.isHidden = false
- self.timeLabel.toolTip = dateString
- } else {
- self.timeLabel.isHidden = true
- }
- let showPage = model?.showPage ?? true
- if showPage {
- self.pageLabel.stringValue = pageString
- let labelsize = self.pageLabel.stringValue.boundingRect(with: NSMakeSize(CGFloat(MAXFLOAT),NSHeight(self.pageLabel.bounds)), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [.font : NSFont.systemFont(ofSize: 12)])
- self.pageLabelWidthConstraint.constant = labelsize.size.width + 5
- } else {
- self.pageLabel.isHidden = true
- }
- let showAuthor = model?.showAuthor ?? true
- if showAuthor {
- self.autherLabel.stringValue = authorString
- self.autherLabel.isHidden = false
- self.autherLabel.sizeToFit()
- } else {
- self.autherLabel.isHidden = true
- }
- let imageView = KMNoteTypeImageView()
- self.typeImageView.image = imageView.noteTypeImage(withType: noteType, color: noteColor ?? .red)
- self.typeImageView.isHidden = false
- self.noteContentBox.isHidden = true
- self.noteImageView.isHidden = true
- self.foldButton.isHidden = true
- self.annotationContentLabel.isHidden = false
- self.noteContentLabel.stringValue = noteString
- self.contentView.isHidden = false
- self.contentViewHidden(false)
- // 默认折叠
- let isFold = model?.isFold() ?? true
-
- if let data = note {
- if data.isKind(of: CPDFMarkupAnnotation.self) {
- let markup = data as! CPDFMarkupAnnotation
- var contentString = KMBOTAAnnotationTool.fetchText(text: markup.markupContent())
- contentString = contentString.replacingOccurrences(of: "\r", with: "")
- contentString = contentString.replacingOccurrences(of: "\n", with: "")
- self.noteContentLabel.stringValue = contentString
- self.foldButton.isHidden = false
- // }
- let attributeStr = NSMutableAttributedString(string: noteString)
- if (markup.markupType() == .highlight) {
- attributeStr.addAttribute(.backgroundColor, value: noteColor as Any, range: NSMakeRange(0, attributeStr.length))
- } else if (markup.markupType() == .strikeOut) {
- attributeStr.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: NSMakeRange(0, attributeStr.length))
- attributeStr.addAttribute(.strikethroughColor, value: noteColor as Any, range: NSMakeRange(0, attributeStr.length))
- } else if (markup.markupType() == .underline) {
- attributeStr.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSMakeRange(0, attributeStr.length))
- attributeStr.addAttribute(.underlineColor, value: noteColor as Any, range: NSMakeRange(0, attributeStr.length))
- }
- self.annotationContentLabel.attributedStringValue = attributeStr
-
- self.isFold = !(model?.isExpand ?? false)
- self.contentViewHidden(false)
- } else if data.isKind(of: CPDFLineAnnotation.self) || noteType == SKNSquareString || noteType == SKNCircleString { // || noteType == SKNInkString
- noteString = data.contents ?? ""
- if let anno = data as? CPDFLineAnnotation, anno.isMeasure {
- noteString = anno.string() ?? ""
- }
- self.annotationContentLabel.stringValue = noteString
- self.isFold = true
- let expand = model?.isExpand ?? false
- if expand {
- self.foldButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
- } else {
- self.foldButton.image = NSImage(named: "KMImageNameBtnTriRightNor")
- }
- self.foldButton.isHidden = false
- self.contentViewHidden(false)
- } else if data.isKind(of: CPDFStampAnnotation.self) {
- if data.isKind(of: CSelfSignAnnotation.self) {
- let newAnnotation = note as! CSelfSignAnnotation
- let type = newAnnotation.annotationType
- var returnString = ""
- if (type == .signFalse) {
- returnString = KMLocalizedString("X", comment: nil)
- } else if (type == .signature) {
- returnString = KMLocalizedString("Check mark", comment: nil)
- } else if (type == .signCircle) {
- returnString = KMLocalizedString("Circle", comment: nil)
- } else if (type == .signLine) {
- returnString = KMLocalizedString("Line", comment: nil)
- } else if (type == .signDot) {
- returnString = KMLocalizedString("Dot", comment: nil)
- } else if (type == .signText) {
- returnString = KMLocalizedString("Text", comment: nil)
- }
- self.annotationContentLabel.stringValue = returnString
- self.isFold = !(model?.isExpand ?? false)
- } else {
- self.annotationContentLabel.isHidden = true
- self.isFold = true
- let expand = model?.isExpand ?? false
- if expand {
- self.foldButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
- } else {
- self.foldButton.image = NSImage(named: "KMImageNameBtnTriRightNor")
- }
- self.noteImageView.isHidden = false
- let anno = note as! CPDFStampAnnotation
- self.noteImageView.image = anno.stampImage()
- self.foldButton.isHidden = false
- self.contentViewHidden(false)
- }
- } else if let anno = data as? CPDFSignatureAnnotation {
- self.annotationContentLabel.isHidden = true
-
- self.noteImageView.isHidden = false
- self.noteImageView.image = anno.signImage
- self.foldButton.isHidden = false
- let expand = model?.isExpand ?? false
- if expand {
- self.foldButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
- } else {
- self.foldButton.image = NSImage(named: "KMImageNameBtnTriRightNor")
- }
- self.contentViewHidden(false)
- } else if data.isKind(of: CPDFTextAnnotation.self) {
- self.foldButton.isHidden = false
- var noteTilte = noteString
- var noteContent = noteTextString
- if noteTilte == noteContent {
- let textArray = noteTilte.components(separatedBy: " ")
- if textArray.count == 2 {
- noteTilte = textArray.first ?? ""
- noteContent = textArray.last ?? ""
- }
- }
-
- if noteTilte.isEmpty {
- self.annotationContentLabel.stringValue = noteContent
- }else{
- self.annotationContentLabel.stringValue = noteTilte
- self.noteContentLabel.stringValue = noteContent
- }
-
- self.isFold = true
- let expand = model?.isExpand ?? false
- if expand {
- self.foldButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
- } else {
- self.foldButton.image = NSImage(named: "KMImageNameBtnTriRightNor")
- }
- if (noteString.isEmpty == false || noteContent.isEmpty == false) {
- self.contentView.isHidden = false
- } else {
- self.contentView.isHidden = true
- self.contentViewHidden(true)
- }
- if (noteTextString.isEmpty == false) {
- self.foldButton.isHidden = false
- }else{
- self.foldButton.isHidden = true
- }
- } else if data is CPDFRedactAnnotation {
- noteString = KMLocalizedString("Redact")
- self.annotationContentLabel.stringValue = noteString
- } else if data is CPDFInkAnnotation {
- self.foldButton.isHidden = false
- self.isFold = true
- let expand = model?.isExpand ?? false
- if expand {
- self.foldButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
- } else {
- self.foldButton.image = NSImage(named: "KMImageNameBtnTriRightNor")
- }
-
- noteString = data.contents ?? ""
- self.annotationContentLabel.stringValue = noteString
- self.contentViewHidden(false)
- } else if data is CPDFFreeTextAnnotation {
- self.annotationContentLabel.stringValue = noteString
- self.imageViewHeightConstraint.constant = self.contentView.frame.size.height
- self.foldButton.isHidden = false
- self.isFold = !(model?.isExpand ?? false)
- self.contentViewHidden(false)
- } else {
- self.annotationContentLabel.stringValue = noteString
- self.isFold = !(model?.isExpand ?? false)
- self.foldButton.isHidden = false
- self.contentViewHidden(false)
- }
- }
- self.autherLayoutConstraint.constant = self.autherLabel.isHidden ? -(self.autherLabel.bounds.size.width) + 10.0 : 10.0
- self.typeImageViewLayoutConstraint.constant = self.typeImageView.isHidden ? -(self.typeImageView.bounds.size.width) : 0.0
- self.contentBoxLayoutConstraint.constant = self.noteContentBox.isHidden ? -(self.noteContentBox.bounds.size.height+8.0) : 8.0
-
- self.needsLayout = true
- }
- }
|