KMGeneralAnnotationViewController.swift 112 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390
  1. //
  2. // KMGeneralAnnotationViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by wanjun on 2023/12/1.
  6. //
  7. import Cocoa
  8. /**
  9. NSString *SKNFreeTextString = @"FreeText";
  10. NSString *SKNTextString = @"Text";
  11. NSString *SKNNoteString = @"Note";
  12. NSString *SKNCircleString = @"Circle";
  13. NSString *SKNSquareString = @"Square";
  14. NSString *SKNMarkUpString = @"MarkUp";
  15. NSString *SKNHighlightString = @"Highlight";
  16. NSString *SKNUnderlineString = @"Underline";
  17. NSString *SKNStrikeOutString = @"StrikeOut";
  18. NSString *SKNLineString = @"Line";
  19. NSString *SKNInkString = @"Ink";
  20. NSString *SKNPDFAnnotationTypeKey = @"type";
  21. NSString *SKNPDFAnnotationBoundsKey = @"bounds";
  22. NSString *SKNPDFAnnotationPageKey = @"page";
  23. NSString *SKNPDFAnnotationPageIndexKey = @"pageIndex";
  24. NSString *SKNPDFAnnotationContentsKey = @"contents";
  25. NSString *SKNPDFAnnotationStringKey = @"string";
  26. NSString *SKNPDFAnnotationColorKey = @"color";
  27. NSString *SKNPDFAnnotationBorderKey = @"border";
  28. NSString *SKNPDFAnnotationLineWidthKey = @"lineWidth";
  29. NSString *SKNPDFAnnotationBorderStyleKey = @"borderStyle";
  30. NSString *SKNPDFAnnotationDashPatternKey = @"dashPattern";
  31. NSString *SKNPDFAnnotationModificationDateKey = @"modificationDate";
  32. NSString *SKNPDFAnnotationUserNameKey = @"userName";
  33. NSString *SKNPDFAnnotationInteriorColorKey = @"interiorColor";
  34. NSString *SKNPDFAnnotationStartLineStyleKey = @"startLineStyle";
  35. NSString *SKNPDFAnnotationEndLineStyleKey = @"endLineStyle";
  36. NSString *SKNPDFAnnotationStartPointKey = @"startPoint";
  37. NSString *SKNPDFAnnotationEndPointKey = @"endPoint";
  38. NSString *SKNPDFAnnotationFontKey = @"font";
  39. NSString *SKNPDFAnnotationFontColorKey = @"fontColor";
  40. NSString *SKNPDFAnnotationFontNameKey = @"fontName";
  41. NSString *SKNPDFAnnotationFontSizeKey = @"fontSize";
  42. NSString *SKNPDFAnnotationAlignmentKey = @"alignment";
  43. NSString *SKNPDFAnnotationRotationKey = @"rotation";
  44. NSString *SKNPDFAnnotationQuadrilateralPointsKey = @"quadrilateralPoints";
  45. NSString *SKNPDFAnnotationIconTypeKey = @"iconType";
  46. NSString *SKNPDFAnnotationPointListsKey = @"pointLists";
  47. */
  48. enum KMActiveAnnotationType: UInt {
  49. case highlight = 0
  50. case strikeOut
  51. case underline
  52. case inkAndLine
  53. case text
  54. case squareAndCircle
  55. case freeText
  56. case selfSignFreeText
  57. }
  58. enum KMFreeTextAnnotationAlignmentType: UInt {
  59. case left = 0
  60. case center
  61. case right
  62. }
  63. let KMColorPickerViewHeight: CGFloat = 64
  64. @objcMembers class KMGeneralAnnotationViewController: NSViewController, NSTextViewDelegate {
  65. var _annotations: [CPDFAnnotation]?
  66. var subType: KMSelfSignAnnotationFreeTextSubType = .none
  67. var _activeAnnotationType: KMActiveAnnotationType = .highlight
  68. var pdfView: CPDFListView?
  69. var annotationModel: CPDFAnnotationModel?
  70. // var annotationCallback: ((CPDFAnnotation) -> Void)?
  71. @IBOutlet private weak var imageBox: NSBox!
  72. @IBOutlet private weak var imageBoxLayoutConstraint: NSLayoutConstraint!
  73. @IBOutlet private weak var textImageBoxView: NSView!
  74. @IBOutlet private weak var textImageBox: KMBox!
  75. @IBOutlet private weak var textAnnotationImageView: NSImageView!
  76. @IBOutlet private weak var textImageBoxButton: NSButton!
  77. @IBOutlet private weak var textImageUpDateButton: NSButton!
  78. @IBOutlet private weak var generalImageBoxView: NSView!
  79. @IBOutlet private weak var generalImageView: NSImageView!
  80. @IBOutlet private weak var fontView: NSView! // 字体
  81. @IBOutlet private weak var fontLabel: NSTextField!
  82. @IBOutlet private weak var fontButton: NSButton!
  83. @IBOutlet private weak var fontPopUpButton: KMPopUpButton!
  84. @IBOutlet private weak var fontSizeComboBox: KMComboBox!
  85. @IBOutlet private weak var fontStylePopUpButton: KMPopUpButton!
  86. @IBOutlet private weak var leftAlignButton: NSButton!
  87. @IBOutlet private weak var centerAlignButton: NSButton!
  88. @IBOutlet private weak var rightAlignButton: NSButton!
  89. @IBOutlet private weak var fontViewTopConstant: NSLayoutConstraint!
  90. @IBOutlet private weak var fontViewCorloPV: KMColorPickerView!
  91. @IBOutlet private weak var fontViewColorPVConstraint: NSLayoutConstraint!
  92. @IBOutlet private weak var rotateView: NSView! // 旋转
  93. @IBOutlet private weak var rotateLabel: NSTextField!
  94. @IBOutlet private weak var leftRotateBox: KMBox!
  95. @IBOutlet private weak var leftRotateButton: NSButton!
  96. @IBOutlet private weak var rightRotateBox: KMBox!
  97. @IBOutlet private weak var rightRotateButton: NSButton!
  98. @IBOutlet private weak var rotateViewTopConstant: NSLayoutConstraint!
  99. @IBOutlet private weak var typeView: NSView! // 类型
  100. @IBOutlet private weak var typeLabel: NSTextField!
  101. @IBOutlet private weak var tureTypeButton: NSButton!
  102. @IBOutlet private weak var falseTypeButton: NSButton!
  103. @IBOutlet private weak var circletypeButton: NSButton!
  104. @IBOutlet private weak var lineTypeButton: NSButton!
  105. @IBOutlet private weak var dotTypeButton: NSButton!
  106. @IBOutlet private weak var typeViewTopConstant: NSLayoutConstraint!
  107. @IBOutlet private weak var dateView: NSView! // 日期
  108. @IBOutlet private weak var dateLabel: NSTextField!
  109. @IBOutlet private weak var datePopUpButton: KMPopUpButton!
  110. @IBOutlet private weak var dateCheckButton: NSButton!
  111. @IBOutlet private weak var dateViewTopConstant: NSLayoutConstraint!
  112. @IBOutlet private weak var iconView: NSView! // 图标
  113. @IBOutlet private weak var iconLabel: NSTextField!
  114. @IBOutlet private weak var commentBox: NSBox!
  115. @IBOutlet private weak var commentButton: NSButton!
  116. @IBOutlet private weak var noteBox: NSBox!
  117. @IBOutlet private weak var noteButton: NSButton!
  118. @IBOutlet private weak var keyBox: NSBox!
  119. @IBOutlet private weak var keyButton: NSButton!
  120. @IBOutlet private weak var helpBox: NSBox!
  121. @IBOutlet private weak var helpButton: NSButton!
  122. @IBOutlet private weak var paragraphBox: NSBox!
  123. @IBOutlet private weak var paragraphButton: NSButton!
  124. @IBOutlet private weak var insertBox: NSBox!
  125. @IBOutlet private weak var insertButton: NSButton!
  126. @IBOutlet private weak var addParagraphBox: NSBox!
  127. @IBOutlet private weak var addParagraphButton: NSButton!
  128. @IBOutlet private weak var iconViewTopConstant: NSLayoutConstraint!
  129. @IBOutlet private weak var iconButtonHeightConstant: NSLayoutConstraint!
  130. @IBOutlet private weak var borderAndLineView: NSView! // 边框
  131. @IBOutlet private weak var borderLabel: NSTextField!
  132. @IBOutlet private weak var borderButton: NSButton!
  133. @IBOutlet private weak var lineWidthComboBox: KMComboBox!
  134. @IBOutlet private weak var lineWidthSlider: NSSlider!
  135. @IBOutlet private weak var lineTypeLabel: NSTextField!
  136. @IBOutlet private weak var lineStyleButton: KMButton!
  137. @IBOutlet private weak var dottedLineStyleButton: KMButton!
  138. @IBOutlet private weak var rightArrowStyleButton: KMButton!
  139. @IBOutlet private weak var lineStyleBox: NSBox!
  140. @IBOutlet private weak var dottedLineStyleBox: NSBox!
  141. @IBOutlet private weak var rightArrowStyleBox: NSBox!
  142. @IBOutlet private weak var borderViewTopConstant: NSLayoutConstraint!
  143. @IBOutlet private weak var fillColorView: NSView!
  144. @IBOutlet private weak var fillColorLabel: NSTextField!
  145. @IBOutlet private weak var fillColorPickerView: KMColorPickerView!
  146. @IBOutlet private weak var fillColorViewTopConstraint: NSLayoutConstraint!
  147. @IBOutlet private weak var opacityView: NSView! // 透明度
  148. @IBOutlet private weak var opacityLabel: NSTextField!
  149. @IBOutlet private weak var opacitySlider: NSSlider!
  150. @IBOutlet private weak var opacityComboBox: KMComboBox!
  151. @IBOutlet private weak var opacityViewTopConstant: NSLayoutConstraint!
  152. @IBOutlet private weak var noteView: NSView! // 笔记
  153. @IBOutlet private weak var noteViewLabel: NSTextField!
  154. @IBOutlet private var noteTextView: NSTextView!
  155. @IBOutlet private weak var noteViewTopConstant: NSLayoutConstraint!
  156. @IBOutlet private weak var colorView: NSView! // 颜色
  157. @IBOutlet private weak var colorTitleLabel: NSTextField!
  158. @IBOutlet private weak var textColorBox: NSBox!
  159. @IBOutlet private weak var textColorBoxConstraint: NSLayoutConstraint!
  160. @IBOutlet private weak var textColorPickerView: KMColorPickerView!
  161. @IBOutlet private weak var borderColorBox: NSBox!
  162. @IBOutlet private weak var borderColorPickerView: KMColorPickerView!
  163. @IBOutlet private weak var borderColorBoxConstraint: NSLayoutConstraint!
  164. @IBOutlet private weak var lineWidthBox: NSBox!
  165. @IBOutlet private weak var widthLabel: NSTextField!
  166. @IBOutlet private weak var widthComboBox: KMComboBox!
  167. @IBOutlet private weak var widthSlider: NSSlider!
  168. @IBOutlet private weak var ColorViewTopConstant: NSLayoutConstraint!
  169. @IBOutlet private weak var textColorPickerViewConstant: NSLayoutConstraint!
  170. var isannotationMode: Bool = false
  171. var selectedAlignmentButtonLayer: CALayer?
  172. var iconButtonArray: [NSBox] = []
  173. var lineStyleCount: Int = 0
  174. var isTextEdit: Bool = false
  175. var fonts: [[String : [String]]]!
  176. var annotationAlignment: KMFreeTextAnnotationAlignmentType = .left
  177. var noteIcons: [NSImage?] = [nil, nil, nil, nil, nil, nil, nil]
  178. private func makeNoteIcons() {
  179. if noteIcons[0] != nil { return }
  180. let bounds = CGRect(origin: .zero, size: NSMakeSize(16, 16))
  181. let annotation = CPDFTextAnnotation()
  182. annotation.bounds = bounds
  183. annotation.color = NSColor.clear
  184. let page = CPDFPage()
  185. page.setBounds(bounds, for: .mediaBox)
  186. page.addAnnotation(annotation)
  187. for i in 0..<7 {
  188. annotation.setIconType(CPDFTextAnnotationIconType(rawValue: i) ?? .comment)
  189. noteIcons[i] = NSImage.bitmapImage(with: NSMakeSize(16, 16), drawingHandler: { rect in
  190. page.draw(with: .mediaBox, to: (NSGraphicsContext.current?.cgContext))
  191. })
  192. }
  193. }
  194. deinit {
  195. NotificationCenter.default.removeObserver(self)
  196. if ((annotationModel?.annotation) != nil) && annotationModel?.annotations.count == 1 {
  197. let keys = ["contents", "markupText"]
  198. for key in keys {
  199. annotationModel?.annotation.removeObserver(self, forKeyPath: key)
  200. }
  201. }
  202. textColorPickerView.target = nil
  203. textColorPickerView.action = nil
  204. borderColorPickerView.target = nil
  205. borderColorPickerView.action = nil
  206. fillColorPickerView.target = nil
  207. fillColorPickerView.action = nil
  208. NSColorPanel.shared.setTarget(nil)
  209. NSColorPanel.shared.setAction(nil)
  210. }
  211. // MARK: View Methods
  212. override func loadView() {
  213. super.loadView()
  214. DispatchQueue.main.async {
  215. if NSColorPanel.shared.isVisible {
  216. NSColorPanel.shared.close()
  217. }
  218. }
  219. isannotationMode = true
  220. fonts = (CPDFAnnotationModel.supportFonts() as! [[String : [String]]])
  221. imageBox.borderColor = KMAppearance.Interactive.s0Color()
  222. imageBox.borderWidth = 1.0
  223. imageBox.fillColor = KMAppearance.Layout.l1Color()
  224. textImageBox.fillColor = KMAppearance.Layout.l1Color()
  225. fontLabel.stringValue = NSLocalizedString("Fonts", comment: "")
  226. fontLabel.textColor = KMAppearance.Layout.h0Color()
  227. colorTitleLabel.stringValue = NSLocalizedString("Color", comment: "")
  228. colorTitleLabel.textColor = KMAppearance.Layout.h0Color()
  229. opacityLabel.stringValue = NSLocalizedString("Opacity", comment: "")
  230. opacityLabel.textColor = KMAppearance.Layout.h1Color()
  231. noteViewLabel.stringValue = NSLocalizedString("Note", comment: "")
  232. noteViewLabel.textColor = KMAppearance.Layout.h0Color()
  233. rotateLabel.stringValue = NSLocalizedString("Rotate", comment: "")
  234. rotateLabel.textColor = KMAppearance.Layout.h0Color()
  235. typeLabel.stringValue = NSLocalizedString("Type", comment: "")
  236. typeLabel.textColor = KMAppearance.Layout.h0Color()
  237. dateLabel.stringValue = NSLocalizedString("Date", comment: "")
  238. dateLabel.textColor = KMAppearance.Layout.h0Color()
  239. iconLabel.stringValue = NSLocalizedString("Icon", comment: "")
  240. iconLabel.textColor = KMAppearance.Layout.h0Color()
  241. borderLabel.stringValue = NSLocalizedString("Line and Border Style", comment: "")
  242. borderLabel.textColor = KMAppearance.Layout.h0Color()
  243. fillColorLabel.stringValue = NSLocalizedString("Fill", comment: "")
  244. fillColorLabel.textColor = KMAppearance.Layout.h0Color()
  245. lineStyleCount = 0
  246. if annotationType == .highlight {
  247. activeAnnotationType = .highlight
  248. } else if annotationType == .strikeOut {
  249. activeAnnotationType = .strikeOut
  250. } else if annotationType == .underline {
  251. activeAnnotationType = .underline
  252. } else if annotationType == .ink || annotationType == .line || annotationType == .arrow {
  253. activeAnnotationType = .inkAndLine
  254. } else if annotationType == .anchored {
  255. activeAnnotationType = .text
  256. } else if annotationType == .circle || annotationType == .square {
  257. borderColorPickerView.isCallColorPanelAction = isannotationMode
  258. textColorPickerView.isCallColorPanelAction = isannotationMode
  259. activeAnnotationType = .squareAndCircle
  260. } else if annotationType == .freeText {
  261. if subType == .date {
  262. colorTitleLabel.stringValue = NSLocalizedString("Fill Color", comment: "")
  263. activeAnnotationType = .selfSignFreeText
  264. } else {
  265. activeAnnotationType = .freeText
  266. }
  267. fontViewCorloPV.isCallColorPanelAction = isannotationMode
  268. var alignmentType: KMFreeTextAnnotationAlignmentType = .left
  269. if annotationModel?.alignment() == .left {
  270. alignmentType = .left
  271. } else if annotationModel?.alignment() == .center {
  272. alignmentType = .center
  273. } else if annotationModel?.alignment() == .right {
  274. alignmentType = .right
  275. }
  276. alignmentTypeSelected(alignmentType)
  277. }
  278. textColorPickerView.isCallColorPanelAction = isannotationMode
  279. borderColorPickerView.isCallColorPanelAction = isannotationMode
  280. if annotationType == .freeText {
  281. fontViewCorloPV.isFreeText = true
  282. } else {
  283. fontViewCorloPV.isFreeText = false
  284. }
  285. if annotationType == .ink || annotationType == .line || annotationType == .arrow || annotationType == .square || annotationType == .circle {
  286. let lineType = annotationModel?.style()
  287. if lineType == .dashed {
  288. let lineType = annotationModel?.dashPattern()
  289. // if lineType.count == 0 {
  290. // let number = NSNumber(value: Float(4))
  291. // annotation.setDashPattern([number])
  292. //
  293. // let userDefaults = UserDefaults.standard
  294. // if annotationType == .ink {
  295. // userDefaults.set(annotationModel?.dashPattern(), forKey: SKInkNoteDashPatternKey)
  296. // } else if annotationType == .line {
  297. // userDefaults.set(annotationModel?.dashPattern(), forKey: SKLineNoteDashPatternKey)
  298. // } else if annotationType == .square {
  299. // userDefaults.set(annotationModel?.dashPattern(), forKey: SKSquareNoteDashPatternKey)
  300. // } else if annotationType == .circle {
  301. // userDefaults.set(annotationModel?.dashPattern(), forKey: SKCircleNoteDashPatternKey)
  302. // } else if annotationType == .freeText {
  303. // userDefaults.set(annotationModel?.dashPattern(), forKey: CFreeTextNoteDashPatternKey)
  304. // }
  305. // }
  306. }
  307. }
  308. opacityComboBox.type = .none
  309. opacityComboBox.comboxRect = opacityComboBox.bounds
  310. lineWidthComboBox.type = .none
  311. lineWidthComboBox.comboxRect = lineWidthComboBox.bounds
  312. widthComboBox.type = .none
  313. widthComboBox.comboxRect = widthComboBox.bounds
  314. fontPopUpButton.type = .arrowDown
  315. fontSizeComboBox.type = .none
  316. fontSizeComboBox.comboxRect = fontSizeComboBox.bounds
  317. fontStylePopUpButton.type = .arrowUpDown
  318. datePopUpButton.type = .arrowUpDown
  319. noteTextView.backgroundColor = KMAppearance.Layout.l1Color()
  320. let views: [NSView] = [fontPopUpButton, fontSizeComboBox, fontStylePopUpButton, lineWidthComboBox, opacityComboBox, widthComboBox, datePopUpButton, noteTextView]
  321. for view in views {
  322. view.wantsLayer = true
  323. view.layer?.borderWidth = 1.0
  324. view.layer?.cornerRadius = 1.0
  325. }
  326. refreshLineTypeUI()
  327. rightArrowStyleButton.isHidden = true
  328. rightArrowStyleBox.isHidden = true
  329. annotationFontReload()
  330. reloadData()
  331. updateViewColor()
  332. if ((annotationModel?.annotation) != nil) && annotationModel?.annotations.count == 1 {
  333. let annotation = annotationModel?.annotation
  334. let keys = ["contents", "markupText"]
  335. for key in keys {
  336. annotation?.addObserver(self, forKeyPath: key, options: [.new, .old], context: nil)
  337. }
  338. }
  339. // NotificationCenter.default.addObserver(self, selector: #selector(alignmentTypeNotification(_:)), name: "KMAnnotationAlignmentTypeNotification1", object: nil)
  340. // NotificationCenter.default.addObserver(self, selector: #selector(loadingUIAndLocalization(_:)), name: "KMPreferenceDidChangeNotificationName", object: nil)
  341. // NotificationCenter.default.addObserver(self, selector: #selector(annotationChangeNotification(_:)), name: CPDFListViewAnnotationsAttributeHasChangeNotification, object: nil)
  342. }
  343. override func viewDidLoad() {
  344. super.viewDidLoad()
  345. // Do view setup here.
  346. }
  347. override func viewDidAppear() {
  348. super.viewDidAppear()
  349. let showConvertDetails = KMPropertiesViewPopController.showChangeColorDetails()
  350. let fileURL = (self.view.window?.windowController?.document as? NSDocument)?.fileURL
  351. if showConvertDetails && (fileURL != nil) {
  352. KMPropertiesViewPopController.defaultManager.showChangeColorDetailsView(self.textColorPickerView.firstButton)
  353. }
  354. }
  355. func reloadData() {
  356. var annotationColor = annotationModel?.color()
  357. if annotationType == .signFalse ||
  358. annotationType == .signTure ||
  359. annotationType == .signDot ||
  360. annotationType == .signCircle ||
  361. annotationType == .signLine {
  362. annotationColor = annotationModel?.color()
  363. } else if annotationType == .square ||
  364. annotationType == .circle {
  365. annotationColor = annotationModel?.color()
  366. } else if annotationType == .freeText || annotationType == .signDate || annotationType == .signText {
  367. annotationColor = annotationModel?.interiorColor()
  368. } else {
  369. annotationColor = annotationModel?.color()
  370. }
  371. let color = annotationColor ?? NSColor.black
  372. // guard let color = annotationColor else { return }
  373. var opacity: CGFloat = 1.0
  374. color.usingColorSpaceName(.calibratedRGB)?.getRed(nil, green: nil, blue: nil, alpha: &opacity)
  375. if annotationType == .signFalse ||
  376. annotationType == .signTure ||
  377. annotationType == .signDot ||
  378. annotationType == .signCircle ||
  379. annotationType == .signLine {
  380. opacity = (annotationModel?.opacity())!
  381. } else if annotationType == .square ||
  382. annotationType == .circle {
  383. opacity = (annotationModel?.opacity())!
  384. } else if annotationType == .freeText || annotationType == .signDate || annotationType == .signText {
  385. opacity = (annotationModel?.interiorOpacity())!
  386. } else {
  387. opacity = (annotationModel?.opacity())!
  388. }
  389. opacitySlider.floatValue = Float(opacity)
  390. opacitySlider.toolTip = "\(Int(opacity * 100))%"
  391. opacityComboBox.stringValue = "\(Int(opacity * 100))%"
  392. if annotationModel?.annotations != nil {
  393. let contextString = annotation.string() ?? ""
  394. noteTextView.string = contextString
  395. noteTextView.textColor = NSColor.labelColor
  396. noteTextView.delegate = self
  397. }
  398. if annotationType == .freeText {
  399. imageBox.contentView = textImageBoxView
  400. textAnnotationImageView.image = annotationModel?.annotationImage
  401. } else if annotationType == .signText || annotationType == .signDate {
  402. imageBox.contentView = generalImageBoxView
  403. generalImageView.image = annotationModel?.annotationImage
  404. } else {
  405. imageBox.contentView = generalImageBoxView
  406. generalImageView.image = annotationModel?.annotationImage
  407. }
  408. if annotationType == .square || annotationType == .circle || annotationType == .line || annotationType == .arrow || annotationType == .ink {
  409. if annotationType == .ink {
  410. textColorPickerView.setColor(color)
  411. } else if annotationType == .square || annotationType == .circle {
  412. var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0, opacity: CGFloat = 0.0
  413. let modelColor = annotationModel?.interiorColor() ?? .black
  414. modelColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &opacity)
  415. let interiorColor = NSColor(red: red, green: green, blue: blue, alpha: (annotationModel?.interiorOpacity())!)
  416. textColorPickerView.setColor(interiorColor)
  417. textColorPickerView.isFillColor = true
  418. borderColorPickerView.setColor(color)
  419. } else if annotationType == .line || annotationType == .arrow {
  420. var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0, opacity: CGFloat = 0.0
  421. let modelColor = annotationModel?.interiorColor() ?? .black
  422. modelColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &opacity)
  423. let interiorColor = NSColor(red: red, green: green, blue: blue, alpha: (annotationModel?.interiorOpacity())!)
  424. textColorPickerView.setColor(interiorColor)
  425. textColorPickerView.isFillColor = true
  426. borderColorPickerView.setColor(color)
  427. }
  428. lineWidthSlider.floatValue = Float(annotationModel?.lineWidth() ?? 1.0)
  429. lineWidthSlider.toolTip = "\(annotationModel?.lineWidth() ?? 1.0) pt"
  430. lineWidthComboBox.stringValue = String(format: "%0.1f pt", (annotationModel?.lineWidth())!)
  431. } else if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  432. if annotationType == .signText || annotationType == .signDate {
  433. if subType == .date {
  434. dateView.isHidden = false
  435. datePopUpButton.removeAllItems()
  436. let freeText = annotation as! KMSelfSignAnnotationFreeText
  437. // self.datePopUpButton.addItems(withTitles: KMSelfSignAnnotationFreeText.fetchAllDateString(includeTime: <#T##Bool#>))
  438. if freeText.dateFormatIndex >= 0, freeText.dateFormatIndex < datePopUpButton.numberOfItems {
  439. datePopUpButton.selectItem(at: freeText.dateFormatIndex)
  440. } else {
  441. datePopUpButton.selectItem(at: 0)
  442. }
  443. dateCheckButton.state = freeText.includeTime ? NSControl.StateValue.on : NSControl.StateValue.off
  444. textColorPickerView.setColor(annotation.color)
  445. }
  446. } else {
  447. lineWidthSlider.minValue = 0.0
  448. lineWidthSlider.floatValue = Float((annotationModel?.lineWidth())!)
  449. lineWidthSlider.toolTip = String(format: "%0.1f pt", (annotationModel?.lineWidth())!)
  450. lineWidthComboBox.stringValue = String(format: "%0.1f pt", (annotationModel?.lineWidth())!)
  451. var alignmentType: KMFreeTextAnnotationAlignmentType = .left
  452. if annotationModel?.alignment() == .left {
  453. alignmentType = .left
  454. } else if annotationModel?.alignment() == .center {
  455. alignmentType = .center
  456. } else if annotationModel?.alignment() == .right {
  457. alignmentType = .right
  458. }
  459. alignmentTypeSelected(alignmentType)
  460. annotationFontReload()
  461. fillColorPickerView.color = annotationModel?.color()
  462. }
  463. fontViewCorloPV.color = annotationModel?.fontColor()
  464. fontSizeComboBox.stringValue = String(format: "%0.1f pt", (annotationModel?.fontSize())!)
  465. } else if annotationType == .highlight || annotationType == .strikeOut || annotationType == .underline || annotationType == .anchored {
  466. textColorPickerView.setColor(color)
  467. }
  468. noteView.isHidden = isannotationMode
  469. if annotationType == .signText || annotationType == .signDate {
  470. if subType == .date {
  471. noteView.isHidden = true
  472. } else {
  473. noteView.isHidden = false
  474. }
  475. }
  476. if annotationModel?.annotations != nil {
  477. noteView.isHidden = annotationModel?.annotation==nil
  478. } else {
  479. if annotationType == .stamp ||
  480. annotationType == .ink ||
  481. annotationType == .square ||
  482. annotationType == .circle ||
  483. annotationType == .arrow ||
  484. annotationType == .line ||
  485. annotationType == .highlight ||
  486. annotationType == .strikeOut ||
  487. annotationType == .underline ||
  488. annotationType == .freeText {
  489. noteView.isHidden = true
  490. } else {
  491. noteView.isHidden = annotationModel?.annotation==nil
  492. }
  493. }
  494. }
  495. // MARK: Set & Get
  496. var annotations: [CPDFAnnotation] {
  497. get {
  498. return annotationModel?.annotations as! [CPDFAnnotation]
  499. }
  500. }
  501. var annotation: CPDFAnnotation {
  502. get {
  503. return (annotationModel?.annotation)!
  504. }
  505. }
  506. var annotationType: CAnnotationType {
  507. get {
  508. return (annotationModel?.annotationType as? CAnnotationType)!
  509. }
  510. }
  511. func updateannotationMode() {
  512. let defaults = UserDefaults.standard
  513. if annotationType == .freeText {
  514. // if ([annotation isKindOfClass:[SKNPDFAnnotationNote class]]) {
  515. // [sud setColor:self.annotation.color forKey:SKNPDFAnnotationColorKey];
  516. // [sud setInteger:self.annotation.iconType forKey:SKAnchoredNoteIconTypeKey];
  517. // }
  518. if annotation.isKind(of: CPDFFreeTextAnnotation.self) {
  519. defaults.safe_setColor(annotation.color, forKey: CFreeTextNoteColorKey)
  520. defaults.safe_setColor((annotation as! CPDFFreeTextAnnotation).fontColor, forKey: CFreeTextNoteFontColorKey)
  521. defaults.set((annotation as! CPDFFreeTextAnnotation).alignment.rawValue, forKey: CFreeTextNoteAlignmentKey)
  522. defaults.set((annotation as! CPDFFreeTextAnnotation).fontName(), forKey: CFreeTextNoteFontNameKey)
  523. defaults.set((annotation as! CPDFFreeTextAnnotation).fontSize(), forKey: CFreeTextNoteFontSizeKey)
  524. defaults.set(annotation.lineWidth(), forKey: CFreeTextNoteLineWidthKey)
  525. defaults.set(annotation.borderStyle().rawValue, forKey: CFreeTextNoteLineStyleKey)
  526. defaults.set(annotation.dashPattern(), forKey: CFreeTextNoteDashPatternKey)
  527. }
  528. } else if annotationType == .circle {
  529. defaults.safe_setColor(annotation.color, forKey: CCircleNoteColorKey)
  530. defaults.safe_setColor((annotation as! CPDFCircleAnnotation).interiorColor, forKey: CCircleNoteInteriorColorKey)
  531. defaults.set(annotation.lineWidth(), forKey: CCircleNoteLineWidthKey)
  532. defaults.set((annotation as! CPDFCircleAnnotation).borderStyle().rawValue, forKey: CCircleNoteLineStyleKey)
  533. defaults.set((annotation as! CPDFCircleAnnotation).dashPattern(), forKey: CCircleNoteDashPatternKey)
  534. } else if annotationType == .square {
  535. defaults.safe_setColor(annotation.color, forKey: CSquareNoteColorKey)
  536. defaults.safe_setColor((annotation as! CPDFSquareAnnotation).interiorColor, forKey: CSquareNoteInteriorColorKey)
  537. defaults.set(annotation.lineWidth(), forKey: CSquareNoteLineWidthKey)
  538. defaults.set((annotation as! CPDFSquareAnnotation).borderStyle().rawValue, forKey: CSquareNoteLineStyleKey)
  539. defaults.set((annotation as! CPDFSquareAnnotation).dashPattern(), forKey: CSquareNoteDashPatternKey)
  540. } else if annotationType == .highlight {
  541. defaults.safe_setColor(annotation.color, forKey: CHighlightNoteColorKey)
  542. } else if annotationType == .underline {
  543. defaults.safe_setColor(annotation.color, forKey: CUnderlineNoteColorKey)
  544. } else if annotationType == .strikeOut {
  545. defaults.safe_setColor(annotation.color, forKey: CStrikeOutNoteColorKey)
  546. } else if annotationType == .line || annotationType == .arrow {
  547. defaults.safe_setColor(annotation.color, forKey: CLineNoteColorKey)
  548. defaults.set(annotation.lineWidth(), forKey: CLineNoteLineWidthKey)
  549. defaults.set(annotation.borderStyle().rawValue, forKey: CLineNoteLineStyleKey)
  550. defaults.set(annotation.dashPattern(), forKey: CLineNoteDashPatternKey)
  551. defaults.safe_setColor((annotation as! CPDFLineAnnotation).interiorColor, forKey: CLineNoteInteriorColorKey)
  552. defaults.set((annotation as! CPDFLineAnnotation).startLineStyle.rawValue, forKey: CLineNoteStartLineStyleKey)
  553. defaults.set((annotation as! CPDFLineAnnotation).endLineStyle.rawValue, forKey: CLineNoteEndLineStyleKey)
  554. } else if annotationType == .ink {
  555. defaults.safe_setColor(annotation.color, forKey: CInkNoteColorKey)
  556. defaults.set(annotation.lineWidth(), forKey: CInkNoteLineWidthKey)
  557. defaults.set(annotation.borderStyle().rawValue, forKey: CInkNoteLineStyleKey)
  558. defaults.set(annotation.dashPattern(), forKey: CInkNoteDashPatternKey)
  559. } else if annotationType == .anchored {
  560. // [sud setColor:self.annotation.color forKey:SKNPDFAnnotationColorKey];
  561. // [sud setInteger:self.annotation.iconType forKey:SKAnchoredNoteIconTypeKey];
  562. }
  563. }
  564. var activeAnnotationType: KMActiveAnnotationType {
  565. set {
  566. _activeAnnotationType = newValue
  567. switch self.activeAnnotationType {
  568. case .highlight, .strikeOut, .underline:
  569. self.fontView.isHidden = true
  570. self.borderAndLineView.isHidden = true
  571. self.fillColorView.isHidden = true
  572. self.rotateView.isHidden = true
  573. self.typeView.isHidden = true
  574. self.dateView.isHidden = true
  575. self.iconView.isHidden = true
  576. self.createMarkupProperties()
  577. case .inkAndLine:
  578. self.fontView.isHidden = true
  579. self.fillColorView.isHidden = true
  580. self.rotateView.isHidden = true
  581. self.typeView.isHidden = true
  582. self.dateView.isHidden = true
  583. self.iconView.isHidden = true
  584. self.createInkAndLineProperties()
  585. case .text:
  586. self.fontView.isHidden = true
  587. self.borderAndLineView.isHidden = true
  588. self.fillColorView.isHidden = true
  589. self.rotateView.isHidden = true
  590. self.typeView.isHidden = true
  591. self.dateView.isHidden = true
  592. self.createTextProperties()
  593. case .squareAndCircle:
  594. self.fontView.isHidden = true
  595. self.rotateView.isHidden = true
  596. self.typeView.isHidden = true
  597. self.dateView.isHidden = true
  598. self.iconView.isHidden = true
  599. self.fillColorView.isHidden = true
  600. self.createSquareAndCircleProperties()
  601. case .freeText:
  602. self.colorView.isHidden = true
  603. self.rotateView.isHidden = true
  604. self.typeView.isHidden = true
  605. self.dateView.isHidden = true
  606. self.iconView.isHidden = true
  607. self.createFreeTextProperties()
  608. case .selfSignFreeText:
  609. self.rotateView.isHidden = true
  610. self.borderAndLineView.isHidden = true
  611. self.fillColorView.isHidden = true
  612. self.typeView.isHidden = true
  613. self.iconView.isHidden = true
  614. self.createSelfSignFreeTextProperties()
  615. default:
  616. break
  617. }
  618. }
  619. get {
  620. return _activeAnnotationType
  621. }
  622. }
  623. // MARK: private
  624. func updateViewColor() {
  625. if KMAppearance.isDarkMode() {
  626. let darkColor = NSColor(red: 57/255.0, green: 60/255.0, blue: 62/255.0, alpha: 1.0).cgColor
  627. let borderColor = NSColor(red: 86/255.0, green: 88/255.0, blue: 90/255.0, alpha: 1.0).cgColor
  628. setViewColor(fontPopUpButton, darkColor, borderColor)
  629. setViewColor(fontSizeComboBox, darkColor, borderColor)
  630. setViewColor(fontStylePopUpButton, darkColor, borderColor)
  631. setViewColor(lineWidthComboBox, darkColor, borderColor)
  632. setViewColor(opacityComboBox, darkColor, borderColor)
  633. setViewColor(datePopUpButton, darkColor, borderColor)
  634. setViewColor(widthComboBox, darkColor, borderColor)
  635. setViewColor(noteTextView, darkColor, borderColor)
  636. } else {
  637. let lightColor = NSColor.white.cgColor
  638. let borderColor = NSColor(red: 218/255.0, green: 219/255.0, blue: 222/255.0, alpha: 1.0).cgColor
  639. setViewColor(fontPopUpButton, lightColor, borderColor)
  640. setViewColor(fontSizeComboBox, lightColor, borderColor)
  641. setViewColor(fontStylePopUpButton, lightColor, borderColor)
  642. setViewColor(lineWidthComboBox, lightColor, borderColor)
  643. setViewColor(opacityComboBox, lightColor, borderColor)
  644. setViewColor(datePopUpButton, lightColor, borderColor)
  645. setViewColor(widthComboBox, lightColor, borderColor)
  646. setViewColor(noteTextView, lightColor, borderColor)
  647. }
  648. }
  649. func setViewColor(_ view: NSView, _ backgroundColor: CGColor, _ borderColor: CGColor) {
  650. view.layer?.backgroundColor = backgroundColor
  651. view.layer?.borderColor = borderColor
  652. }
  653. func refreshLineTypeUI() {
  654. lineStyleBox.borderColor = KMAppearance.Interactive.s0Color()
  655. dottedLineStyleBox.borderColor = KMAppearance.Interactive.s0Color()
  656. rightArrowStyleBox.borderColor = KMAppearance.Interactive.s0Color()
  657. lineStyleBox.fillColor = KMAppearance.Layout.l1Color()
  658. dottedLineStyleBox.fillColor = KMAppearance.Layout.l1Color()
  659. rightArrowStyleBox.fillColor = KMAppearance.Layout.l1Color()
  660. lineStyleBox.borderWidth = 1
  661. dottedLineStyleBox.borderWidth = 1
  662. rightArrowStyleBox.borderWidth = 1
  663. if lineStyleCount == 0 {
  664. lineStyleBox.fillColor = KMAppearance.Status.selColor()
  665. lineStyleBox.borderWidth = 0.0
  666. } else if lineStyleCount == 1 {
  667. dottedLineStyleBox.fillColor = KMAppearance.Status.selColor()
  668. dottedLineStyleBox.borderWidth = 0
  669. } else if lineStyleCount == 2 {
  670. rightArrowStyleBox.fillColor = KMAppearance.Status.selColor()
  671. rightArrowStyleBox.borderWidth = 0
  672. }
  673. }
  674. func hiddenSubviews() {
  675. fontViewTopConstant.constant = fontView.isHidden ? -(fontView.bounds.size.height) - 20 : 10
  676. ColorViewTopConstant.constant = colorView.isHidden ? -(colorView.bounds.size.height) : 10
  677. borderViewTopConstant.constant = borderAndLineView.isHidden ? -(borderAndLineView.bounds.size.height) : 20
  678. opacityViewTopConstant.constant = opacityView.isHidden ? -opacityView.bounds.size.height : 20
  679. rotateViewTopConstant.constant = rotateView.isHidden ? -(rotateView.bounds.size.height) : 20
  680. typeViewTopConstant.constant = typeView.isHidden ? -(typeView.bounds.size.height) : 20
  681. dateViewTopConstant.constant = dateView.isHidden ? -(dateView.bounds.size.height) : 20
  682. iconViewTopConstant.constant = iconView.isHidden ? -(iconView.bounds.size.height) : 20
  683. noteViewTopConstant.constant = noteView.isHidden ? -(noteView.bounds.size.height) : 20
  684. fillColorViewTopConstraint.constant = fillColorView.isHidden ? -fillColorView.bounds.size.height : 20
  685. fontViewColorPVConstraint.constant = fontViewCorloPV.isHidden ? -fontViewCorloPV.bounds.size.height : 10
  686. }
  687. func setActiveAnnotationType(_ activeAnnotationType: KMActiveAnnotationType) {
  688. self.activeAnnotationType = activeAnnotationType
  689. switch activeAnnotationType {
  690. case .highlight, .strikeOut, .underline:
  691. fontView.isHidden = true
  692. borderAndLineView.isHidden = true
  693. fillColorView.isHidden = true
  694. rotateView.isHidden = true
  695. typeView.isHidden = true
  696. dateView.isHidden = true
  697. iconView.isHidden = true
  698. createMarkupProperties()
  699. case .inkAndLine:
  700. fontView.isHidden = true
  701. fillColorView.isHidden = true
  702. rotateView.isHidden = true
  703. typeView.isHidden = true
  704. dateView.isHidden = true
  705. iconView.isHidden = true
  706. createInkAndLineProperties()
  707. case .text:
  708. fontView.isHidden = true
  709. borderAndLineView.isHidden = true
  710. fillColorView.isHidden = true
  711. rotateView.isHidden = true
  712. typeView.isHidden = true
  713. dateView.isHidden = true
  714. createTextProperties()
  715. case .squareAndCircle:
  716. fontView.isHidden = true
  717. rotateView.isHidden = true
  718. typeView.isHidden = true
  719. dateView.isHidden = true
  720. iconView.isHidden = true
  721. fillColorView.isHidden = true
  722. createSquareAndCircleProperties()
  723. case .freeText:
  724. colorView.isHidden = true
  725. rotateView.isHidden = true
  726. typeView.isHidden = true
  727. dateView.isHidden = true
  728. iconView.isHidden = true
  729. createFreeTextProperties()
  730. case .selfSignFreeText:
  731. rotateView.isHidden = true
  732. borderAndLineView.isHidden = true
  733. fillColorView.isHidden = true
  734. typeView.isHidden = true
  735. iconView.isHidden = true
  736. createSelfSignFreeTextProperties()
  737. default:
  738. break
  739. }
  740. }
  741. func createMarkupProperties() {
  742. let colorViewHeight = colorTitleLabel.frame.height + KMColorPickerViewHeight + 30
  743. colorView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: colorViewHeight)
  744. textColorBoxConstraint.constant = 10
  745. borderColorBoxConstraint.constant = 0
  746. textColorBox.isHidden = true
  747. lineWidthBox.isHidden = true
  748. imageBoxLayoutConstraint.constant = generalImageBoxView.frame.height
  749. hiddenSubviews()
  750. textColorPickerView.noContentString = true
  751. if activeAnnotationType == .highlight {
  752. textColorPickerView.annotationTypeString = NSLocalizedString("Highlight", comment: "Description for export")
  753. } else if activeAnnotationType == .strikeOut {
  754. textColorPickerView.annotationTypeString = NSLocalizedString("Strikethrough", comment: "Description for export")
  755. } else if activeAnnotationType == .underline {
  756. textColorPickerView.annotationTypeString = NSLocalizedString("Underline", comment: "Description for export")
  757. }
  758. textColorPickerView.annotationType = (activeAnnotationType == .highlight) ? .markupHighlightColors : .markupOtherColors
  759. }
  760. func openFreeTextStylesViewController() {
  761. if annotations.count == 0 {
  762. return
  763. }
  764. let vc = KMFreeTextStylesViewController()
  765. vc.annotations = annotations
  766. vc.view.frame = CGRect(x: 0, y: 0, width: 280, height: CGRectGetHeight(self.view.window?.frame ?? CGRect.zero) - 300)
  767. let createFilePopover = NSPopover()
  768. createFilePopover.contentViewController = vc
  769. createFilePopover.animates = true
  770. createFilePopover.behavior = .transient
  771. createFilePopover.show(relativeTo: CGRect(x: textImageBox.bounds.origin.x, y: 10, width: textImageBox.bounds.size.width, height: textImageBox.bounds.size.height), of: textImageBox, preferredEdge: .minY)
  772. // Assuming _textImageBox is an NSView instance
  773. createFilePopover.show(relativeTo: textImageBox.bounds, of: textImageBox, preferredEdge: .minY)
  774. // Release is not needed in Swift due to automatic reference counting (ARC)
  775. }
  776. func changeStoredFontInfo(_ sender: Any) {
  777. // if let senderFont = sender as? NSFont {
  778. // for tAnnotation in self.annotations {
  779. // tAnnotation.removeAllAppearanceStreams()
  780. // let font = senderFont.convert(tAnnotation.font)
  781. // if let validFont = font {
  782. // tAnnotation.font = validFont
  783. // }
  784. // }
  785. // }
  786. }
  787. private func updateAnnotation() {
  788. if annotationModel?.annotation != nil {
  789. if annotation is CPDFFreeTextAnnotation {
  790. let textNote = (annotation as! CPDFFreeTextAnnotation)
  791. if let isEdit = pdfView?.isEdit(withCurrentFreeText: textNote), isEdit {
  792. // pdfView?.commitEditAnnotationFreeText(textNote)
  793. pdfView?.editAnnotationFreeText(textNote)
  794. }
  795. pdfView?.setNeedsDisplay(pdfView?.activeAnnotation)
  796. }
  797. for tAnnotation in annotations {
  798. if tAnnotation is CPDFStampAnnotation {
  799. (tAnnotation as? KMSelfSignAnnotation)?.updateAppearanceStream()
  800. }
  801. if tAnnotation is CPDFMarkupAnnotation {
  802. pdfView?.setNeedsDisplayFor(tAnnotation.page)
  803. } else {
  804. pdfView?.setNeedsDisplayAnnotationViewFor(tAnnotation.page)
  805. }
  806. }
  807. }
  808. if annotationType == .freeText {
  809. textAnnotationImageView.image = annotationModel?.annotationImage
  810. } else {
  811. generalImageView.image = annotationModel?.annotationImage
  812. }
  813. }
  814. override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  815. if self.annotation.isEqual(to: object) == false {
  816. return
  817. }
  818. let newValue = change?[NSKeyValueChangeKey.newKey] as? NSObject
  819. let oldValue = change?[NSKeyValueChangeKey.oldKey]
  820. if let data = newValue?.isEqual(to: oldValue), data {
  821. return
  822. }
  823. if keyPath == "string" {
  824. if newValue == nil || newValue is NSNull {
  825. return
  826. }
  827. //处理编辑时光标后移
  828. if self.isTextEdit == false {
  829. self.noteTextView.string = newValue as? String ?? ""
  830. }
  831. self.isTextEdit = false
  832. } else {
  833. self.reloadData()
  834. if self.isannotationMode {
  835. self.updateannotationMode()
  836. }
  837. }
  838. }
  839. // MARK: Line Note
  840. func createInkAndLineProperties() {
  841. if annotationType == .ink {
  842. let colorViewHeight = CGRectGetHeight(colorTitleLabel.frame) + KMColorPickerViewHeight + 30
  843. colorView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: colorViewHeight)
  844. textColorBoxConstraint.constant = 10
  845. borderColorBoxConstraint.constant = 0
  846. textColorBox.isHidden = true
  847. lineWidthBox.isHidden = true
  848. imageBoxLayoutConstraint.constant = CGRectGetHeight(generalImageBoxView.frame)
  849. hiddenSubviews()
  850. textColorPickerView.noContentString = true
  851. textColorPickerView.annotationTypeString = NSLocalizedString("Line Color", comment: "")
  852. textColorPickerView.annotationType = .inkColors
  853. } else if annotationType == .line || annotationType == .arrow {
  854. let colorViewHeight = CGRectGetHeight(colorTitleLabel.frame) + KMColorPickerViewHeight * 2 + 40
  855. colorView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: colorViewHeight)
  856. textColorBoxConstraint.constant = KMColorPickerViewHeight + 20
  857. borderColorBoxConstraint.constant = 0
  858. lineWidthBox.isHidden = true
  859. textColorPickerViewConstant.constant = 57
  860. imageBoxLayoutConstraint.constant = CGRectGetHeight(generalImageBoxView.frame)
  861. hiddenSubviews()
  862. borderColorPickerView.annotationTypeString = NSLocalizedString("Line Color", comment: "")
  863. textColorPickerView.annotationTypeString = NSLocalizedString("Fill Color", comment: "")
  864. borderColorPickerView.annotationType = .lineColors
  865. textColorPickerView.annotationType = .lineFillColors
  866. borderColorPickerView.annotationTypeString = NSLocalizedString("Line Color", comment: "")
  867. borderColorPickerView.annotationType = .lineColors
  868. }
  869. lineTypeLabel.stringValue = NSLocalizedString("Line and Border Style", comment: "")
  870. lineTypeLabel.textColor = KMAppearance.Layout.h0Color()
  871. lineWidthSlider.floatValue = Float((annotationModel?.lineWidth())!)
  872. lineWidthComboBox.stringValue = String(format: "%0.1f pt", (annotationModel?.lineWidth())!)
  873. lineStyleButton.wantsLayer = true
  874. dottedLineStyleButton.wantsLayer = true
  875. rightArrowStyleButton.wantsLayer = true
  876. lineStyleButton.image = borderStyleSolid(false)
  877. dottedLineStyleButton.image = borderStyleDashed(false)
  878. rightArrowStyleButton.image = lineStyleRightArrow(false)
  879. if annotationModel?.style() == .solid {
  880. lineStyleCount = 0
  881. lineStyleButton.image = borderStyleSolid(true)
  882. lineStyleBox.borderWidth = 0
  883. lineStyleBox.fillColor = KMAppearance.Status.selColor()
  884. } else if annotationModel?.style() == .dashed {
  885. lineStyleCount = 1
  886. dottedLineStyleButton.image = borderStyleDashed(true)
  887. dottedLineStyleBox.borderWidth = 0
  888. dottedLineStyleBox.fillColor = KMAppearance.Status.selColor()
  889. }
  890. if (annotationType == .line || annotationType == .arrow) && annotationModel?.endLineStyle() == .closedArrow {
  891. lineStyleCount = 2
  892. rightArrowStyleButton.image = lineStyleRightArrow(true)
  893. rightArrowStyleBox.borderWidth = 0
  894. rightArrowStyleBox.fillColor = KMAppearance.Status.selColor()
  895. }
  896. }
  897. func createTextProperties() {
  898. makeNoteIcons()
  899. let colorViewHeight = colorTitleLabel.frame.height + KMColorPickerViewHeight + 30
  900. colorView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: colorViewHeight)
  901. textColorBoxConstraint.constant = 10
  902. borderColorBoxConstraint.constant = 0
  903. textColorBox.isHidden = true
  904. lineWidthBox.isHidden = true
  905. imageBoxLayoutConstraint.constant = generalImageBoxView.frame.height
  906. hiddenSubviews()
  907. textColorPickerView.annotationTypeString = NSLocalizedString("Anchored Note", comment: "Description for export")
  908. commentButton.title = NSLocalizedString("Comment", comment: "")
  909. commentButton.toolTip = NSLocalizedString("Comment", comment: "")
  910. commentButton.setTitleColor(KMAppearance.Layout.h0Color())
  911. paragraphButton.title = NSLocalizedString("Paragraph", comment: "")
  912. paragraphButton.toolTip = NSLocalizedString("Paragraph", comment: "")
  913. paragraphButton.setTitleColor(KMAppearance.Layout.h0Color())
  914. insertButton.title = NSLocalizedString("Insert", comment: "")
  915. insertButton.toolTip = NSLocalizedString("Insert", comment: "")
  916. insertButton.setTitleColor(KMAppearance.Layout.h0Color())
  917. addParagraphButton.title = NSLocalizedString("New Paragraph", comment: "")
  918. addParagraphButton.toolTip = NSLocalizedString("New Paragraph", comment: "")
  919. addParagraphButton.setTitleColor(KMAppearance.Layout.h0Color())
  920. keyButton.title = NSLocalizedString("Key", comment: "")
  921. keyButton.toolTip = NSLocalizedString("Key", comment: "")
  922. keyButton.setTitleColor(KMAppearance.Layout.h0Color())
  923. noteButton.title = NSLocalizedString("Note", comment: "")
  924. noteButton.toolTip = NSLocalizedString("Note", comment: "")
  925. noteButton.setTitleColor(KMAppearance.Layout.h0Color())
  926. helpButton.title = NSLocalizedString("Help", comment: "")
  927. helpButton.toolTip = NSLocalizedString("Help", comment: "")
  928. helpButton.setTitleColor(KMAppearance.Layout.h0Color())
  929. let languages = NSLocale.preferredLanguages
  930. var currentLocaleLanguageCode = "en"
  931. if let firstLanguage = languages.first {
  932. currentLocaleLanguageCode = firstLanguage
  933. if currentLocaleLanguageCode.hasPrefix("zh") {
  934. currentLocaleLanguageCode = "zh"
  935. }
  936. }
  937. let buttonArray: [NSButton] = [commentButton, keyButton, noteButton, helpButton, addParagraphButton, paragraphButton, insertButton]
  938. for button in buttonArray {
  939. button.wantsLayer = true
  940. button.layer?.cornerRadius = 6.0
  941. if currentLocaleLanguageCode == "zh" {
  942. iconButtonHeightConstant.constant = 56.0
  943. button.imagePosition = .imageAbove
  944. } else {
  945. iconButtonHeightConstant.constant = 50.0
  946. button.imagePosition = .imageOnly
  947. }
  948. }
  949. iconButtonArray = [commentBox, keyBox, noteBox, helpBox, addParagraphBox, paragraphBox, insertBox]
  950. let iconType = UInt((annotationModel?.anchoredIconType().rawValue)!)
  951. clickAnnotationTextIconButtonAction(iconType: iconType, boxArr: iconButtonArray)
  952. textColorPickerView.annotationType = .anchoredNoteColors
  953. textColorPickerView.isCallColorPanelAction = true
  954. }
  955. func clickAnnotationTextIconButtonAction(iconType: UInt, boxArr buttonArr: [NSBox]) {
  956. for i in 0..<buttonArr.count {
  957. if iconType == 0 {
  958. commentButton.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
  959. commentButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteAnnotationSel)
  960. } else {
  961. commentButton.layer?.backgroundColor = NSColor.clear.cgColor
  962. commentButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteAnnotationNor)
  963. }
  964. if iconType == 1 {
  965. keyButton.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
  966. keyButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteKeywordSel)
  967. } else {
  968. keyButton.layer?.backgroundColor = NSColor.clear.cgColor
  969. keyButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteKeywordNor)
  970. }
  971. if iconType == 2 {
  972. noteButton.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
  973. noteButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteNotesSel)
  974. } else {
  975. noteButton.layer?.backgroundColor = NSColor.clear.cgColor
  976. noteButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteNotesNor)
  977. }
  978. if iconType == 3 {
  979. helpButton.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
  980. helpButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteHelpSel)
  981. } else {
  982. helpButton.layer?.backgroundColor = NSColor.clear.cgColor
  983. helpButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteHelpNor)
  984. }
  985. if iconType == 4 {
  986. addParagraphButton.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
  987. addParagraphButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteNewparagraphSel)
  988. } else {
  989. addParagraphButton.layer?.backgroundColor = NSColor.clear.cgColor
  990. addParagraphButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteNewparagraphNor)
  991. }
  992. if iconType == 5 {
  993. paragraphButton.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
  994. paragraphButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteParagraphSel)
  995. } else {
  996. paragraphButton.layer?.backgroundColor = NSColor.clear.cgColor
  997. paragraphButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteParagraphNor)
  998. }
  999. if iconType == 6 {
  1000. insertButton.layer?.backgroundColor = KMAppearance.Status.selColor().cgColor
  1001. insertButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteInsertSel)
  1002. } else {
  1003. insertButton.layer?.backgroundColor = NSColor.clear.cgColor
  1004. insertButton.image = NSImage(named: KMImageNameUXIconPropertybarNoteInsertNor)
  1005. }
  1006. }
  1007. }
  1008. func borderStyleSolid(_ isSelect: Bool) -> NSImage {
  1009. let size = NSSize(width: 49.0, height: 12.0)
  1010. let image = NSImage(size: size, flipped: false, drawingHandler: { rect in
  1011. let path = NSBezierPath(rect: NSRect(x: 15.0, y: 5.0, width: 20.0, height: 1.0))
  1012. path.lineWidth = 2.0
  1013. isSelect ? KMAppearance.Layout.m_1Color().setStroke() : KMAppearance.Layout.m_1Color().setStroke()
  1014. path.stroke()
  1015. return true
  1016. })
  1017. return image
  1018. }
  1019. func borderStyleDashed(_ isSelect: Bool) -> NSImage {
  1020. let size = NSSize(width: 49.0, height: 12.0)
  1021. let image = NSImage(size: size, flipped: false, drawingHandler: { rect in
  1022. let path = NSBezierPath()
  1023. path.move(to: NSPoint(x: 15.0, y: 5.0))
  1024. path.line(to: NSPoint(x: 19.0, y: 5.0))
  1025. path.move(to: NSPoint(x: 23.0, y: 5.0))
  1026. path.line(to: NSPoint(x: 27.0, y: 5.0))
  1027. path.move(to: NSPoint(x: 31.0, y: 5.0))
  1028. path.line(to: NSPoint(x: 35.0, y: 5.0))
  1029. path.lineWidth = 2.0
  1030. isSelect ? KMAppearance.Layout.m_1Color().setStroke() : KMAppearance.Layout.m_1Color().setStroke()
  1031. path.stroke()
  1032. return true
  1033. })
  1034. return image
  1035. }
  1036. func lineStyleRightArrow(_ isSelect: Bool) -> NSImage {
  1037. let size = NSSize(width: 49.0, height: 12.0)
  1038. let image = NSImage(size: size, flipped: false, drawingHandler: { rect in
  1039. let path = NSBezierPath()
  1040. path.move(to: NSPoint(x: 6.0, y: 6.0))
  1041. path.line(to: NSPoint(x: 43.0, y: 6.0))
  1042. path.move(to: NSPoint(x: 32.0, y: 3.0))
  1043. path.line(to: NSPoint(x: 43.0, y: 6.0))
  1044. path.line(to: NSPoint(x: 32.0, y: 9.0))
  1045. path.close()
  1046. path.lineWidth = 2.0
  1047. if isSelect {
  1048. KMAppearance.Layout.l0Color().setStroke()
  1049. } else {
  1050. KMAppearance.Interactive.s0Color().setStroke()
  1051. }
  1052. path.stroke()
  1053. return true
  1054. })
  1055. return image
  1056. }
  1057. // MARK: SKSquareNote、SKCircleNote、SKArrowNote Properties
  1058. func createSquareAndCircleProperties() {
  1059. let colorViewHeight = CGRectGetHeight(colorTitleLabel.frame) + KMColorPickerViewHeight * 2 + 40
  1060. colorView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: colorViewHeight)
  1061. textColorBoxConstraint.constant = KMColorPickerViewHeight + 20
  1062. borderColorBoxConstraint.constant = 0
  1063. lineWidthBox.isHidden = true
  1064. textColorPickerViewConstant.constant = 57
  1065. imageBoxLayoutConstraint.constant = CGRectGetHeight(generalImageBoxView.frame)
  1066. hiddenSubviews()
  1067. lineTypeLabel.stringValue = NSLocalizedString("Line and Border Style", comment: "")
  1068. lineTypeLabel.textColor = KMAppearance.Layout.h0Color()
  1069. lineWidthSlider.floatValue = Float((annotationModel?.lineWidth())!)
  1070. lineWidthComboBox.stringValue = String(format: "%0.1f pt", (annotationModel?.lineWidth())!)
  1071. textColorPickerView.annotationTypeString = NSLocalizedString("Fill Color", comment: "")
  1072. borderColorPickerView.annotationTypeString = NSLocalizedString("Line Color", comment: "")
  1073. textColorPickerView.annotationType = .lineFillColors
  1074. borderColorPickerView.annotationType = .lineColors
  1075. lineStyleButton.wantsLayer = true
  1076. dottedLineStyleButton.wantsLayer = true
  1077. rightArrowStyleButton.wantsLayer = true
  1078. lineStyleButton.image = borderStyleSolid(false)
  1079. dottedLineStyleButton.image = borderStyleDashed(false)
  1080. if annotationModel?.annotation != nil {
  1081. if annotationModel?.annotation.borderStyle() == .solid {
  1082. lineStyleCount = 0
  1083. lineStyleButton.image = borderStyleSolid(true)
  1084. lineStyleBox.borderWidth = 0
  1085. lineStyleBox.fillColor = KMAppearance.Status.selColor()
  1086. } else if annotationModel?.annotation.borderStyle() == .dashed {
  1087. lineStyleCount = 1
  1088. dottedLineStyleButton.image = borderStyleDashed(true)
  1089. dottedLineStyleBox.borderWidth = 1
  1090. dottedLineStyleBox.fillColor = KMAppearance.Status.selColor()
  1091. }
  1092. } else {
  1093. if annotationModel?.style() == .solid {
  1094. lineStyleCount = 0
  1095. lineStyleButton.image = borderStyleSolid(true)
  1096. lineStyleBox.borderWidth = 0
  1097. lineStyleBox.fillColor = KMAppearance.Status.selColor()
  1098. } else if annotationModel?.style() == .dashed {
  1099. lineStyleCount = 1
  1100. dottedLineStyleButton.image = borderStyleDashed(true)
  1101. dottedLineStyleBox.borderWidth = 1
  1102. dottedLineStyleBox.fillColor = KMAppearance.Status.selColor()
  1103. }
  1104. }
  1105. }
  1106. // MARK: SKFreeTextNote、PDFAnnotationFreeText Properties
  1107. func createFreeTextProperties() {
  1108. imageBox.fillColor = KMAppearance.Layout.w0Color()
  1109. textColorBox.isHidden = true
  1110. lineWidthBox.isHidden = true
  1111. imageBoxLayoutConstraint.constant = CGRectGetHeight(textImageBoxView.frame)
  1112. textImageBox.downCallback = { [weak self] downEntered, mouseBox, event in
  1113. if downEntered {
  1114. self?.openFreeTextStylesViewController()
  1115. }
  1116. }
  1117. textImageUpDateButton.wantsLayer = true
  1118. textImageBoxButton.image = NSImage(named: KMImageNameUXIconBtnTriDownNor)
  1119. textImageBoxButton.isEnabled = true
  1120. textImageUpDateButton.title = NSLocalizedString("Click to refresh", comment: "")
  1121. textImageUpDateButton.setTitleColor(KMAppearance.Layout.w0Color())
  1122. textImageUpDateButton.layer?.cornerRadius = 1.0
  1123. textImageUpDateButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
  1124. textImageUpDateButton.isHidden = true
  1125. hiddenSubviews()
  1126. fontViewCorloPV.noContentString = true
  1127. fontViewCorloPV.annotationTypeString = NSLocalizedString("Color", comment: "")
  1128. fillColorPickerView.noContentString = true
  1129. fillColorPickerView.annotationTypeString = NSLocalizedString("Color", comment: "")
  1130. lineTypeLabel.stringValue = NSLocalizedString("Line and Border Style", comment: "")
  1131. lineTypeLabel.textColor = KMAppearance.Layout.h0Color()
  1132. leftAlignButton.toolTip = NSLocalizedString("Left Alignment", comment: "")
  1133. centerAlignButton.toolTip = NSLocalizedString("Center", comment: "")
  1134. rightAlignButton.toolTip = NSLocalizedString("Right Alignment", comment: "")
  1135. lineWidthSlider.floatValue = Float((annotationModel?.lineWidth())!)
  1136. lineWidthComboBox.stringValue = String(format: "%0.1f pt", Float((annotationModel?.lineWidth())!))
  1137. leftRotateBox.borderColor = KMAppearance.Interactive.s0Color()
  1138. leftRotateBox.borderWidth = 0.5
  1139. leftRotateButton.image = NSImage(named: KMImageNameUXIconPropertybarRotateCounterclockwiseNor)
  1140. leftRotateBox.downCallback = { [weak self] downEntered, mouseBox, event in
  1141. if downEntered {
  1142. self?.leftRotateBox.fillColor = KMAppearance.Status.selColor()
  1143. self?.leftRotateButton.image = NSImage(named: KMImageNameUXIconPropertybarRotateCounterclockwisePre)
  1144. } else {
  1145. self?.leftRotateBox.fillColor = KMAppearance.Layout.w0Color()
  1146. self?.leftRotateButton.image = NSImage(named: KMImageNameUXIconPropertybarRotateCounterclockwiseNor)
  1147. }
  1148. }
  1149. rightRotateBox.borderColor = KMAppearance.Interactive.s0Color()
  1150. rightRotateBox.borderWidth = 0.5
  1151. rightRotateButton.image = NSImage(named: KMImageNameUXIconPropertybarRotateClockwiseNor)
  1152. rightRotateBox.downCallback = { [weak self] downEntered, mouseBox, event in
  1153. if downEntered {
  1154. self?.rightRotateBox.fillColor = KMAppearance.Status.selColor()
  1155. self?.rightRotateButton.image = NSImage(named: KMImageNameUXIconPropertybarRotateClockwisePre)
  1156. } else {
  1157. self?.rightRotateBox.fillColor = KMAppearance.Layout.w0Color()
  1158. self?.rightRotateButton.image = NSImage(named: KMImageNameUXIconPropertybarRotateClockwiseNor)
  1159. }
  1160. }
  1161. lineStyleButton.wantsLayer = true
  1162. dottedLineStyleButton.wantsLayer = true
  1163. rightArrowStyleButton.wantsLayer = true
  1164. lineStyleButton.image = borderStyleSolid(false)
  1165. dottedLineStyleButton.image = borderStyleDashed(false)
  1166. if annotationModel?.style() == .solid {
  1167. lineStyleCount = 0
  1168. lineStyleButton.image = borderStyleSolid(true)
  1169. lineStyleBox.borderWidth = 0
  1170. lineStyleBox.fillColor = KMAppearance.Status.selColor()
  1171. lineStyleBox.borderWidth = 0
  1172. } else if annotationModel?.style() == .dashed {
  1173. lineStyleCount = 1
  1174. dottedLineStyleButton.image = borderStyleDashed(true)
  1175. dottedLineStyleBox.fillColor = KMAppearance.Status.selColor()
  1176. dottedLineStyleBox.borderWidth = 0
  1177. } else {
  1178. lineStyleCount = 0
  1179. lineStyleButton.image = borderStyleSolid(true)
  1180. lineStyleBox.borderWidth = 0
  1181. lineStyleBox.fillColor = KMAppearance.Status.selColor()
  1182. lineStyleBox.borderWidth = 0
  1183. }
  1184. fontViewCorloPV.annotationType = .freeTextColors
  1185. fillColorPickerView.annotationType = .freeTextFillColors
  1186. }
  1187. func alignmentTypeSelected(_ type: KMFreeTextAnnotationAlignmentType) {
  1188. annotationAlignment = type
  1189. selectedAlignmentButtonLayer?.removeFromSuperlayer()
  1190. selectedAlignmentButtonLayer = CALayer()
  1191. selectedAlignmentButtonLayer?.cornerRadius = 6.0
  1192. leftAlignButton.wantsLayer = true
  1193. centerAlignButton.wantsLayer = true
  1194. rightAlignButton.wantsLayer = true
  1195. selectedAlignmentButtonLayer?.bounds = leftAlignButton.layer?.bounds ?? CGRect.zero
  1196. selectedAlignmentButtonLayer?.anchorPoint = CGPoint(x: 0, y: 0)
  1197. var color = NSColor(red: 71/255.0, green: 126/255.0, blue: 222/255.0, alpha: 0.16)
  1198. if #available(macOS 10.14, *) {
  1199. let appearanceName = NSApp.effectiveAppearance.bestMatch(from: [.aqua, .darkAqua])
  1200. if appearanceName == .darkAqua {
  1201. color = NSColor(red: 34/255.0, green: 122/255.0, blue: 255/255.0, alpha: 0.3)
  1202. }
  1203. }
  1204. selectedAlignmentButtonLayer?.backgroundColor = color.cgColor
  1205. leftAlignButton.image = NSImage(named: KMImageNameUXIconPropertybarTextalignLeftNor)
  1206. centerAlignButton.image = NSImage(named: KMImageNameUXIconPropertybarTextalignCenterNor)
  1207. rightAlignButton.image = NSImage(named: KMImageNameUXIconPropertybarTextalignRightNor)
  1208. if type == .left {
  1209. leftAlignButton.image = NSImage(named: KMImageNameUXIconPropertybarTextalignLeftSel)
  1210. } else if type == .center {
  1211. centerAlignButton.image = NSImage(named: KMImageNameUXIconPropertybarTextalignCenterSel)
  1212. } else if type == .right {
  1213. rightAlignButton.image = NSImage(named: KMImageNameUXIconPropertybarTextalignRightSel)
  1214. }
  1215. DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { [weak self] in
  1216. guard let self = self else { return }
  1217. if type == .left {
  1218. self.leftAlignButton.layer?.insertSublayer(self.selectedAlignmentButtonLayer!, at: 0)
  1219. } else if type == .center {
  1220. self.centerAlignButton.layer?.insertSublayer(self.selectedAlignmentButtonLayer!, at: 0)
  1221. } else if type == .right {
  1222. self.rightAlignButton.layer?.insertSublayer(self.selectedAlignmentButtonLayer!, at: 0)
  1223. }
  1224. }
  1225. }
  1226. // MARK: SKFreeTextNote、KMSelfSignAnnotationFreeText Properties
  1227. func createSelfSignFreeTextProperties() {
  1228. let colorViewHeight = CGRectGetHeight(colorTitleLabel.frame) + KMColorPickerViewHeight + 30
  1229. colorView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: colorViewHeight)
  1230. textColorBoxConstraint.constant = 10
  1231. borderColorBoxConstraint.constant = 0
  1232. textColorBox.isHidden = true
  1233. lineWidthBox.isHidden = true
  1234. imageBoxLayoutConstraint.constant = CGRectGetHeight(generalImageBoxView.frame)
  1235. hiddenSubviews()
  1236. fontViewTopConstant.constant = colorView.frame.size.height + opacityView.frame.size.height - 10 + 10
  1237. ColorViewTopConstant.constant = -(fontView.frame.size.height + fontViewTopConstant.constant)
  1238. dateViewTopConstant.constant = fontView.frame.size.height + 30
  1239. fontViewCorloPV.noContentString = true
  1240. fontViewCorloPV.annotationTypeString = ""
  1241. textColorPickerView.annotationTypeString = NSLocalizedString("Background", comment: "")
  1242. dateCheckButton.title = NSLocalizedString("Time", comment: "")
  1243. if let attrTitle = dateCheckButton.attributedTitle.mutableCopy() as? NSMutableAttributedString {
  1244. let len = attrTitle.length
  1245. let range = NSRange(location: 0, length: len)
  1246. attrTitle.addAttribute(.foregroundColor, value: KMAppearance.Layout.h1Color(), range: range)
  1247. attrTitle.fixAttributes(in: range)
  1248. dateCheckButton.attributedTitle = attrTitle
  1249. }
  1250. if activeAnnotationType == .selfSignFreeText { // 添加日期 字体默认颜色不要透明色
  1251. textColorPickerView.annotationType = .freeTextFillColors
  1252. fontViewCorloPV.annotationType = .freeTextColors
  1253. } else {
  1254. textColorPickerView.annotationType = .freeTextColors
  1255. fontViewCorloPV.annotationType = .freeTextFillColors
  1256. }
  1257. }
  1258. func setFontStyle(fontName: String, currentStyle style: String?) -> UInt {
  1259. var selectIndex: UInt = 0
  1260. let menu = NSMenu()
  1261. if let fontFamily = NSFontManager.shared.availableMembers(ofFontFamily: fontName) {
  1262. for i in 0..<fontFamily.count {
  1263. let array = fontFamily[i]
  1264. if let styleName = array[1] as? String {
  1265. if style == styleName {
  1266. selectIndex = UInt(i)
  1267. }
  1268. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: fontName, NSFontDescriptor.AttributeName.face: styleName])
  1269. let font = NSFont(descriptor: attributeFontDescriptor, size: 12.0)
  1270. let attrited = [NSAttributedString.Key.font: font]
  1271. let string = NSAttributedString(string: styleName, attributes: attrited)
  1272. let item = NSMenuItem()
  1273. item.attributedTitle = string
  1274. menu.addItem(item)
  1275. }
  1276. }
  1277. }
  1278. if style == nil {
  1279. selectIndex = 0
  1280. }
  1281. fontStylePopUpButton.menu = menu
  1282. return selectIndex
  1283. }
  1284. // MARK: UI Action
  1285. @IBAction func colorPickerViewAction(_ sender: Any) {
  1286. var fillColor: NSColor = NSColor.clear
  1287. var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0, opacity: CGFloat = 0.0
  1288. if let textColor = textColorPickerView.color {
  1289. textColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &opacity)
  1290. if fabs(opacity - 0) < 0.001 {
  1291. if annotationType == .square || annotationType == .circle || annotationType == .line || annotationType == .arrow {
  1292. annotationModel?.setInteriorOpacity(0)
  1293. annotationModel?.setInteriorColor(.black)
  1294. } else if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1295. annotationModel?.setOpacity(0)
  1296. annotationModel?.setFontColor(.black)
  1297. } else {
  1298. annotationModel?.setOpacity(0)
  1299. annotationModel?.setFontColor(.black)
  1300. }
  1301. } else {
  1302. if annotationType == .square || annotationType == .circle || annotationType == .line || annotationType == .arrow {
  1303. annotationModel?.setInteriorOpacity(opacity)
  1304. annotationModel?.setInteriorColor(textColor)
  1305. } else if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1306. annotationModel?.setOpacity(opacity)
  1307. annotationModel?.setFontColor(textColor)
  1308. } else {
  1309. annotationModel?.setOpacity(opacity)
  1310. annotationModel?.setColor(textColor)
  1311. }
  1312. }
  1313. opacitySlider.floatValue = Float(opacity)
  1314. let color = NSColor(calibratedRed: red, green: green, blue: blue, alpha: opacity)
  1315. fillColor = color
  1316. if annotationModel?.annotations != nil {
  1317. if annotationModel?.annotation is CPDFFreeTextAnnotation {
  1318. let textNote = (annotationModel?.annotation as! CPDFFreeTextAnnotation)
  1319. if let isEdit = pdfView?.isEdit(withCurrentFreeText: textNote), isEdit {
  1320. pdfView?.setEditAnnotationFreeTextColor(textColor, freeText: textNote)
  1321. } else {
  1322. updateAnnotation()
  1323. }
  1324. } else {
  1325. updateAnnotation()
  1326. }
  1327. generalImageView.image = annotationModel?.annotationImage
  1328. } else {
  1329. updateAnnotation()
  1330. }
  1331. }
  1332. }
  1333. @IBAction func fillColorPickerViewAction(_ sender: Any) {
  1334. var fillColor = NSColor.clear
  1335. var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0, opacity: CGFloat = 0.0
  1336. if let borderColor = borderColorPickerView.color {
  1337. borderColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &opacity)
  1338. opacitySlider.floatValue = Float(opacity)
  1339. let color = NSColor(calibratedRed: red, green: green, blue: blue, alpha: opacity)
  1340. fillColor = color
  1341. }
  1342. if annotationType == .freeText {
  1343. if let fillColorPickerColor = fillColorPickerView.color {
  1344. fillColorPickerColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &opacity)
  1345. opacitySlider.floatValue = Float(opacity)
  1346. let color = NSColor(calibratedRed: red, green: green, blue: blue, alpha: opacity)
  1347. annotationModel?.setColor(color)
  1348. annotationModel?.setOpacity(opacity)
  1349. }
  1350. } else {
  1351. annotationModel?.setColor(fillColor)
  1352. annotationModel?.setOpacity(opacity)
  1353. }
  1354. updateAnnotation()
  1355. }
  1356. @IBAction func fontViewCorloPVAction(_ sender: Any) {
  1357. // var fillColor: NSColor = NSColor.clear
  1358. // var red: CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0, opacity: CGFloat = 0.0
  1359. //
  1360. // if let textColor = fontViewCorloPV.color {
  1361. // textColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &opacity)
  1362. // if fabs(opacity - 0) < 0.001 {
  1363. // if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1364. // annotationModel?.setOpacity(0)
  1365. // annotationModel?.setFontColor(.black)
  1366. // } else {
  1367. // annotationModel?.setOpacity(0)
  1368. // annotationModel?.setFontColor(.black)
  1369. // }
  1370. // } else {
  1371. // if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1372. // annotationModel?.setOpacity(opacity)
  1373. // annotationModel?.setFontColor(textColor)
  1374. // } else {
  1375. // annotationModel?.setOpacity(opacity)
  1376. // annotationModel?.setColor(textColor)
  1377. // }
  1378. // }
  1379. //
  1380. // opacitySlider.floatValue = Float(opacity)
  1381. //
  1382. // if annotationModel?.annotation != nil {
  1383. // if annotationModel?.annotation is CPDFFreeTextAnnotation {
  1384. // let textNote = (annotationModel?.annotation as! CPDFFreeTextAnnotation)
  1385. // if let isEdit = pdfView?.isEdit(withCurrentFreeText: textNote), isEdit {
  1386. // pdfView?.setEditAnnotationFreeTextColor(textColor, freeText: textNote)
  1387. // } else {
  1388. // updateAnnotation()
  1389. // }
  1390. // } else {
  1391. // updateAnnotation()
  1392. // }
  1393. // generalImageView.image = annotationModel?.annotationImage
  1394. // } else {
  1395. // updateAnnotation()
  1396. // }
  1397. // }
  1398. if annotationType == .freeText {
  1399. annotationModel?.setFontColor(fontViewCorloPV.color)
  1400. } else {
  1401. annotationModel?.setColor(fontViewCorloPV.color)
  1402. }
  1403. updateAnnotation()
  1404. }
  1405. @IBAction func opacitySliderAction(_ sender: Any) {
  1406. var opcity = CGFloat(opacitySlider.floatValue)
  1407. if opcity == 0 {
  1408. opcity = 0.0001
  1409. }
  1410. if annotationType == .signFalse ||
  1411. annotationType == .signTure ||
  1412. annotationType == .signDot ||
  1413. annotationType == .signCircle ||
  1414. annotationType == .signLine {
  1415. annotationModel?.setOpacity(opcity)
  1416. } else if annotationType == .square ||
  1417. annotationType == .circle {
  1418. if opcity != 0 {
  1419. annotationModel?.setOpacity(opcity)
  1420. annotationModel?.setInteriorOpacity(opcity)
  1421. } else {
  1422. annotationModel?.setColor(nil)
  1423. annotationModel?.setInteriorColor(nil)
  1424. }
  1425. } else if annotationType == .freeText || annotationType == .signDate || annotationType == .signText {
  1426. annotationModel?.setOpacity(opcity)
  1427. var color = annotationModel?.fontColor()
  1428. if annotationModel?.opacity() != 0 {
  1429. var red: CGFloat = 0.0
  1430. var green: CGFloat = 0.0
  1431. var blue: CGFloat = 0.0
  1432. var opacity: CGFloat = 0.0
  1433. color?.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &opacity)
  1434. color = NSColor(red: red, green: green, blue: blue, alpha: (annotationModel?.opacity())!)
  1435. } else {
  1436. color = .clear
  1437. }
  1438. } else {
  1439. annotationModel?.setOpacity(opcity)
  1440. }
  1441. opacityComboBox.stringValue = "\(Int(opcity * 100))%"
  1442. updateAnnotation()
  1443. }
  1444. @IBAction func opacityComboBoxAction(_ sender: Any) {
  1445. opacitySlider.floatValue = Float(opacityComboBox.floatValue / 100)
  1446. var opcity = CGFloat(opacitySlider.floatValue)
  1447. if opcity == 0 {
  1448. opcity = 0.0001
  1449. }
  1450. if annotationType == .signFalse ||
  1451. annotationType == .signTure ||
  1452. annotationType == .signDot ||
  1453. annotationType == .signCircle ||
  1454. annotationType == .signLine {
  1455. annotationModel?.setOpacity(opcity)
  1456. } else if annotationType == .square ||
  1457. annotationType == .circle {
  1458. if opcity != 0 {
  1459. annotationModel?.setOpacity(opcity)
  1460. annotationModel?.setInteriorOpacity(opcity)
  1461. } else {
  1462. annotationModel?.setColor(nil)
  1463. annotationModel?.setInteriorColor(nil)
  1464. }
  1465. } else if annotationType == .freeText || annotationType == .signDate || annotationType == .signText {
  1466. annotationModel?.setInteriorOpacity(opcity)
  1467. } else {
  1468. annotationModel?.setOpacity(opcity)
  1469. }
  1470. opacitySlider.floatValue = Float(opcity)
  1471. opacitySlider.toolTip = "\(Int(opcity * 100))%"
  1472. updateAnnotation()
  1473. }
  1474. @IBAction func lineWidthSliderAction(_ sender: Any) {
  1475. annotationModel?.setLineWidth(CGFloat(lineWidthSlider.floatValue))
  1476. lineWidthComboBox.stringValue = String(format: "%0.1f pt", (annotationModel?.lineWidth())!)
  1477. updateAnnotation()
  1478. }
  1479. @IBAction func lineWidthComboBoxAction(_ sender: Any) {
  1480. var lineWidth = lineWidthComboBox.floatValue
  1481. if lineWidth > 18 {
  1482. lineWidth = 18
  1483. } else if lineWidth < 0.5 {
  1484. lineWidth = 0.5
  1485. }
  1486. annotationModel?.setLineWidth(CGFloat(lineWidth))
  1487. lineWidthSlider.floatValue = Float((annotationModel?.lineWidth())!)
  1488. updateAnnotation()
  1489. }
  1490. @IBAction func alignButtonAction(_ sender: NSButton) {
  1491. var alignmentType: KMFreeTextAnnotationAlignmentType = .left
  1492. if annotationModel?.annotations != nil {
  1493. for tAnnotation in self.annotations {
  1494. switch sender.tag {
  1495. case 0:
  1496. if tAnnotation is CPDFFreeTextAnnotation {
  1497. (tAnnotation as! CPDFFreeTextAnnotation).alignment = .left
  1498. }
  1499. alignmentType = .left
  1500. case 1:
  1501. if tAnnotation is CPDFFreeTextAnnotation {
  1502. (tAnnotation as! CPDFFreeTextAnnotation).alignment = .center
  1503. }
  1504. alignmentType = .center
  1505. case 2:
  1506. if tAnnotation is CPDFFreeTextAnnotation {
  1507. (tAnnotation as! CPDFFreeTextAnnotation).alignment = .right
  1508. }
  1509. alignmentType = .right
  1510. default:
  1511. break
  1512. }
  1513. }
  1514. } else {
  1515. switch sender.tag {
  1516. case 0:
  1517. annotationModel?.setAlignment(.left)
  1518. alignmentType = .left
  1519. case 1:
  1520. annotationModel?.setAlignment(.center)
  1521. alignmentType = .center
  1522. case 2:
  1523. annotationModel?.setAlignment(.right)
  1524. alignmentType = .right
  1525. default:
  1526. break
  1527. }
  1528. }
  1529. alignmentTypeSelected(alignmentType)
  1530. updateAnnotation()
  1531. NotificationCenter.default.post(name: NSNotification.Name("KMAnnotationAlignmentTypeNotification"),
  1532. object: "\(alignmentType.rawValue)")
  1533. }
  1534. @IBAction func currentFontColorButtonAction(_ sender: NSButton) {
  1535. // if ([_annotation isKindOfClass:[PDFAnnotationFreeText class]]) {
  1536. // KMFontColorViewController *vc = [[[KMFontColorViewController alloc] initWithNibName:@"KMFontColorViewController" bundle:[NSBundle mainBundle]] autorelease];
  1537. // vc.annotationFontColor = _annotation.fontColor;
  1538. // __block typeof(self) blockSelf = self;
  1539. // vc.fontColorChangeCallback = ^(NSColor *fontColor) {
  1540. // for (PDFAnnotation *tAnnotation in blockSelf.annotations) {
  1541. // tAnnotation.fontColor = fontColor;
  1542. // }
  1543. // };
  1544. // NSPopover *popover = [[NSPopover alloc] init];
  1545. // popover.delegate = self;
  1546. // popover.contentViewController = vc;
  1547. // popover.animates = YES;
  1548. // popover.behavior = NSPopoverBehaviorTransient;
  1549. // [popover showRelativeToRect:CGRectMake([sender bounds].origin.x, 0, [sender bounds].size.width, [sender bounds].size.height) ofView:sender preferredEdge:CGRectMaxYEdge];
  1550. // [popover release];
  1551. // }
  1552. }
  1553. @IBAction func borderButtonAction(_ sender: NSButton) {
  1554. var lineWidth: CGFloat = 0.0
  1555. var lineStype: CPDFBorderStyle = .solid
  1556. var startingPoint: CPDFLineStyle = .none
  1557. var endPoint: CPDFLineStyle = .none
  1558. var dashPattern: [NSNumber] = []
  1559. var isLineAnnotation: Bool = false
  1560. if annotationModel?.annotations != nil {
  1561. for tAnnotation in self.annotations {
  1562. lineWidth = tAnnotation.lineWidth()
  1563. lineStype = tAnnotation.borderStyle()
  1564. dashPattern = tAnnotation.dashPattern() as! [NSNumber]
  1565. if tAnnotation is CPDFLineAnnotation {
  1566. isLineAnnotation = true
  1567. startingPoint = (tAnnotation as! CPDFLineAnnotation).startLineStyle
  1568. endPoint = (tAnnotation as! CPDFLineAnnotation).endLineStyle
  1569. } else {
  1570. isLineAnnotation = false
  1571. }
  1572. }
  1573. } else {
  1574. lineWidth = String(format: "%0.1f pt", (annotationModel?.lineWidth())!).stringToCGFloat()
  1575. lineStype = (annotationModel?.style())! as CPDFBorderStyle
  1576. dashPattern = (annotationModel?.dashPattern())! as [NSNumber]
  1577. if annotationModel?.annotationType == .line {
  1578. isLineAnnotation = true
  1579. startingPoint = (annotationModel?.startLineStyle())! as CPDFLineStyle
  1580. endPoint = (annotationModel?.endLineStyle())! as CPDFLineStyle
  1581. } else {
  1582. isLineAnnotation = false
  1583. }
  1584. }
  1585. let lineModel = KMLineModel(lineWidth: lineWidth, lineStype: lineStype, startingPoint: startingPoint, endPoint: endPoint, dashPattern: dashPattern, isLineAnnotation: isLineAnnotation)
  1586. let fontWindowController = KMAnnotationLineWindowController.initWindowController(lineModel)
  1587. guard let window = fontWindowController.window else { return }
  1588. // fontWindowController.annotationLineChangeBlock = { [weak self] lineNote in
  1589. // if lineNote.borderStyle() == .solid {
  1590. // self!.lineTypeButtonAction(self!.lineStyleButton)
  1591. // } else if lineNote.borderStyle() == .dashed {
  1592. // self!.lineTypeButtonAction(self!.dottedLineStyleButton)
  1593. // for tAnnotation in self!.annotations {
  1594. // tAnnotation.setDashPattern(lineNote.dashPattern())
  1595. // }
  1596. // }
  1597. // }
  1598. fontWindowController.callback = { model in
  1599. if self.annotationModel?.annotations != nil {
  1600. } else {
  1601. }
  1602. }
  1603. window.orderFront(sender)
  1604. }
  1605. func lineTypePopAction() {
  1606. annotationModel?.setStyle(CPDFBorderStyle(rawValue: lineStyleCount) ?? .solid)
  1607. updateAnnotation()
  1608. }
  1609. @IBAction func lineTypeButtonAction(_ sender: NSButton) {
  1610. let tag = sender.tag
  1611. switch tag {
  1612. case 0:
  1613. lineStyleCount = 0
  1614. refreshLineTypeUI()
  1615. lineStyleButton.image = borderStyleSolid(true)
  1616. dottedLineStyleButton.image = borderStyleDashed(false)
  1617. rightArrowStyleButton.image = lineStyleRightArrow(false)
  1618. lineTypePopAction()
  1619. case 1:
  1620. lineStyleCount = 1
  1621. refreshLineTypeUI()
  1622. lineStyleButton.image = borderStyleSolid(false)
  1623. dottedLineStyleButton.image = borderStyleDashed(true)
  1624. rightArrowStyleButton.image = lineStyleRightArrow(false)
  1625. lineTypePopAction()
  1626. case 2:
  1627. lineStyleCount = 2
  1628. refreshLineTypeUI()
  1629. lineStyleButton.image = borderStyleSolid(false)
  1630. dottedLineStyleButton.image = borderStyleDashed(false)
  1631. rightArrowStyleButton.image = lineStyleRightArrow(true)
  1632. for tAnnotation in annotations {
  1633. if tAnnotation is CPDFLineAnnotation {
  1634. (tAnnotation as! CPDFLineAnnotation).endLineStyle = .closedArrow
  1635. }
  1636. }
  1637. default:
  1638. break
  1639. }
  1640. }
  1641. @IBAction func iconButtonAction(_ sender: NSButton) {
  1642. var type: CPDFTextAnnotationIconType = .comment
  1643. switch sender.tag {
  1644. case 0:
  1645. type = .comment
  1646. case 1:
  1647. type = .key
  1648. case 2:
  1649. type = .note
  1650. case 3:
  1651. type = .help
  1652. case 4:
  1653. type = .newParagraph
  1654. case 5:
  1655. type = .paragraph
  1656. case 6, _:
  1657. type = .insert
  1658. }
  1659. if annotationModel?.annotations != nil {
  1660. for tAnnotation in self.annotations {
  1661. if tAnnotation is CPDFTextAnnotation {
  1662. (tAnnotation as! CPDFTextAnnotation).setIconType(type)
  1663. }
  1664. }
  1665. self.updateAnnotation()
  1666. } else {
  1667. annotationModel?.setAnchoredIconType(type)
  1668. }
  1669. generalImageView.image = annotationModel?.annotationImage
  1670. updateannotationMode()
  1671. clickAnnotationTextIconButtonAction(iconType: UInt(sender.tag), boxArr: iconButtonArray)
  1672. }
  1673. @IBAction func textImageBoxButtonAction(_ sender: Any) {
  1674. openFreeTextStylesViewController()
  1675. }
  1676. // MARK: Font、FontSize Action
  1677. @IBAction func fontButtonAction(_ sender: NSButton) {
  1678. let selectItem = self.fontPopUpButton.selectedItem
  1679. guard let selectItem = selectItem else { return }
  1680. let resultAtt = NSMutableAttributedString(attributedString: selectItem.attributedTitle!)
  1681. let familyString = resultAtt.string
  1682. let styleString = self.fontStylePopUpButton.selectedItem?.title
  1683. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [.family: familyString, .face: styleString as Any])
  1684. let fontSizeString = fontSizeComboBox.stringValue.replacingOccurrences(of: " pt", with: "")
  1685. let newFont = NSFont(descriptor: attributeFontDescriptor, size: fontSizeString.stringToCGFloat())
  1686. let fontModel = KMFontModel(fontName: familyString, fontWeight: styleString!, fontSize: fontSizeString.stringToCGFloat(), fontColor: textColorPickerView.color ?? .black, fontAlignment: annotationAlignment, annotationType: annotationModel!.annotationType)
  1687. let fontWindowController = KMAnnotationFontWindowController.initWindowController(fontModel)
  1688. let window = fontWindowController.window
  1689. fontWindowController.callback = { [weak self] model in
  1690. self!.alignmentTypeSelected(model.fontAlignment)
  1691. self!.textColorPickerView.color = model.fontColor
  1692. DispatchQueue.global(qos: .default).async {
  1693. let fonts = NSFontManager.shared.availableFontFamilies
  1694. let menu = NSMenu()
  1695. var selectedIndex = 0
  1696. for (index, fontName) in fonts.enumerated() {
  1697. if let font = NSFont(name: fontName, size: 12.0) {
  1698. let attributedString = NSAttributedString(string: fontName, attributes: [.font: font])
  1699. let item = NSMenuItem()
  1700. item.attributedTitle = attributedString
  1701. menu.addItem(item)
  1702. if model.fontName == font.fontName {
  1703. selectedIndex = index
  1704. }
  1705. }
  1706. }
  1707. DispatchQueue.main.async {
  1708. self!.fontPopUpButton.menu = menu
  1709. self!.fontPopUpButton.selectItem(at: selectedIndex)
  1710. }
  1711. }
  1712. let selectedStyleIndex = self!.setFontStyle(fontName: model.fontName, currentStyle: model.fontWeight)
  1713. self!.fontStylePopUpButton.selectItem(at: Int(selectedStyleIndex))
  1714. self!.fontSizeComboBox.stringValue = String(format: "%.f pt", model.fontSize)
  1715. if self!.annotationModel?.annotations != nil {
  1716. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [.family: model.fontName, .face: model.fontWeight])
  1717. let annotationFont = NSFont(descriptor: attributeFontDescriptor, size: model.fontSize)
  1718. for tAnnotation in self!.annotations {
  1719. if tAnnotation is CPDFFreeTextAnnotation {
  1720. (tAnnotation as! CPDFFreeTextAnnotation).font = annotationFont
  1721. (tAnnotation as! CPDFFreeTextAnnotation).fontColor = model.fontColor
  1722. if model.fontAlignment == .left {
  1723. (tAnnotation as! CPDFFreeTextAnnotation).alignment = .left
  1724. } else if model.fontAlignment == .center {
  1725. (tAnnotation as! CPDFFreeTextAnnotation).alignment = .center
  1726. } else if model.fontAlignment == .right {
  1727. (tAnnotation as! CPDFFreeTextAnnotation).alignment = .right
  1728. }
  1729. }
  1730. }
  1731. self!.updateAnnotation()
  1732. } else {
  1733. self!.annotationModel?.setFontName(model.fontName)
  1734. self!.annotationModel?.setFontSize(model.fontSize)
  1735. self!.annotationModel?.setFontColor(model.fontColor)
  1736. if model.fontAlignment == .left {
  1737. self!.annotationModel?.setAlignment(.left)
  1738. } else if model.fontAlignment == .center {
  1739. self!.annotationModel?.setAlignment(.center)
  1740. } else if model.fontAlignment == .right {
  1741. self!.annotationModel?.setAlignment(.right)
  1742. }
  1743. }
  1744. }
  1745. window?.orderFront(sender)
  1746. }
  1747. @IBAction func fontPopUpButtonAction(_ sender: NSPopUpButton) {
  1748. guard let selectedItem = fontPopUpButton.selectedItem else { return }
  1749. let resultAtt = NSMutableAttributedString(attributedString: selectedItem.attributedTitle!)
  1750. let familyString = resultAtt.string
  1751. let selectIndex = setFontStyle(fontName: familyString, currentStyle: nil)
  1752. guard let styleString = fontStylePopUpButton.selectedItem?.title else { return }
  1753. fontStylePopUpButton.selectItem(at: Int(selectIndex))
  1754. if annotationModel?.annotations != nil {
  1755. for tAnnotation in annotations {
  1756. if tAnnotation is CPDFFreeTextAnnotation {
  1757. let newAnnotation = (tAnnotation as! CPDFFreeTextAnnotation)
  1758. if let font = newAnnotation.font {
  1759. if let fontSize = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? String {
  1760. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: familyString, NSFontDescriptor.AttributeName.face: styleString])
  1761. if let newFont = NSFont(descriptor: attributeFontDescriptor, size: fontSize.stringToCGFloat()) {
  1762. newAnnotation.font = newFont
  1763. }
  1764. }
  1765. if let tFont = newAnnotation.font {
  1766. if let family = tFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String,
  1767. let style = tFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.face) as? String {
  1768. DispatchQueue.main.async {
  1769. let selectedStyleIndex = self.setFontStyle(fontName: family, currentStyle: style)
  1770. self.fontStylePopUpButton.selectItem(at: Int(selectedStyleIndex))
  1771. }
  1772. }
  1773. }
  1774. }
  1775. } else if tAnnotation is KMSelfSignAnnotationFreeText {
  1776. let newAnnotation = (tAnnotation as! KMSelfSignAnnotationFreeText)
  1777. if let font = newAnnotation.font {
  1778. if let fontSize = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? String {
  1779. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: familyString, NSFontDescriptor.AttributeName.face: styleString])
  1780. if let newFont = NSFont(descriptor: attributeFontDescriptor, size: fontSize.stringToCGFloat()) {
  1781. newAnnotation.font = newFont
  1782. }
  1783. }
  1784. newAnnotation.updateBounds()
  1785. if let tFont = newAnnotation.font {
  1786. if let family = tFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String,
  1787. let style = tFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.face) as? String {
  1788. DispatchQueue.main.async {
  1789. let selectedStyleIndex = self.setFontStyle(fontName: family, currentStyle: style)
  1790. self.fontStylePopUpButton.selectItem(at: Int(selectedStyleIndex))
  1791. }
  1792. }
  1793. }
  1794. }
  1795. }
  1796. }
  1797. } else {
  1798. if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1799. let font = NSFont(name: (annotationModel?.fontName())!, size: (annotationModel?.fontSize())!) ?? NSFont.systemFont(ofSize: 16)
  1800. if let fontSize = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? String {
  1801. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: familyString, NSFontDescriptor.AttributeName.face: styleString])
  1802. if let newFont = NSFont(descriptor: attributeFontDescriptor, size: fontSize.stringToCGFloat()) {
  1803. annotationModel?.setFontName(newFont.fontName)
  1804. annotationModel?.setFontSize(newFont.pointSize)
  1805. }
  1806. }
  1807. let tFont = NSFont(name: (annotationModel?.fontName())!, size: (annotationModel?.fontSize())!) ?? NSFont.systemFont(ofSize: 16)
  1808. if let family = tFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String,
  1809. let style = tFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.face) as? String {
  1810. DispatchQueue.main.async {
  1811. let selectedStyleIndex = self.setFontStyle(fontName: family, currentStyle: style)
  1812. self.fontStylePopUpButton.selectItem(at: Int(selectedStyleIndex))
  1813. }
  1814. }
  1815. }
  1816. }
  1817. updateAnnotation()
  1818. }
  1819. @IBAction func fontSizeComboBoxAction(_ sender: NSComboBox) {
  1820. if annotationModel?.annotations != nil {
  1821. for tAnnotation in annotations {
  1822. if tAnnotation is CPDFFreeTextAnnotation {
  1823. let newAnnotation = (tAnnotation as! CPDFFreeTextAnnotation)
  1824. if let font = newAnnotation.font {
  1825. let newFont = NSFont(name: font.fontName, size: CGFloat(fontSizeComboBox.floatValue))
  1826. if let newFont = newFont {
  1827. newAnnotation.font = newFont
  1828. }
  1829. }
  1830. } else if tAnnotation is KMSelfSignAnnotationFreeText {
  1831. let newAnnotation = (tAnnotation as! KMSelfSignAnnotationFreeText)
  1832. if let font = newAnnotation.font {
  1833. let newFont = NSFont(name: font.fontName, size: CGFloat(fontSizeComboBox.floatValue))
  1834. if let newFont = newFont {
  1835. newAnnotation.font = newFont
  1836. }
  1837. }
  1838. newAnnotation.updateBounds()
  1839. }
  1840. }
  1841. } else {
  1842. if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1843. let font = NSFont(name: (annotationModel?.fontName()!)!, size: (annotationModel?.fontSize())!) ?? NSFont.systemFont(ofSize: 16)
  1844. let newFont = NSFont(name: font.fontName, size: CGFloat(fontSizeComboBox.floatValue))
  1845. if let newFont = newFont {
  1846. annotationModel?.setFontName(newFont.fontName)
  1847. annotationModel?.setFontSize(newFont.pointSize)
  1848. }
  1849. }
  1850. }
  1851. updateAnnotation()
  1852. NotificationCenter.default.post(name: NSNotification.Name("KMAnnotationFontTypeNotification"),
  1853. object: pdfView)
  1854. adjustFreeText()
  1855. }
  1856. //字重 NSFontWeight
  1857. @IBAction func fontStylePopUpButtonAction(_ sender: NSPopUpButton) {
  1858. if let styleString = self.fontStylePopUpButton.selectedItem?.title {
  1859. if annotationModel?.annotations != nil {
  1860. for tAnnotation in self.annotations {
  1861. if tAnnotation is CPDFFreeTextAnnotation {
  1862. let newAnnotation = (tAnnotation as! CPDFFreeTextAnnotation)
  1863. if let font = newAnnotation.font {
  1864. if let fontSize = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? String,
  1865. let familyString = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String {
  1866. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: familyString, NSFontDescriptor.AttributeName.face: styleString])
  1867. if let newFont = NSFont(descriptor: attributeFontDescriptor, size: fontSize.stringToCGFloat()) {
  1868. newAnnotation.font = newFont
  1869. }
  1870. }
  1871. }
  1872. } else if tAnnotation is KMSelfSignAnnotationFreeText {
  1873. let newAnnotation = (tAnnotation as! KMSelfSignAnnotationFreeText)
  1874. if let font = newAnnotation.font {
  1875. if let fontSize = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? String,
  1876. let familyString = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String {
  1877. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: familyString, NSFontDescriptor.AttributeName.face: styleString])
  1878. if let newFont = NSFont(descriptor: attributeFontDescriptor, size: fontSize.stringToCGFloat()) {
  1879. newAnnotation.font = newFont
  1880. }
  1881. newAnnotation.updateBounds()
  1882. }
  1883. }
  1884. }
  1885. }
  1886. } else {
  1887. if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1888. let font = NSFont(name: (annotationModel?.fontName())!, size: (annotationModel?.fontSize())!) ?? NSFont.systemFont(ofSize: 16)
  1889. if let fontSize = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? String,
  1890. let familyString = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String {
  1891. let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: familyString, NSFontDescriptor.AttributeName.face: styleString])
  1892. if let newFont = NSFont(descriptor: attributeFontDescriptor, size: fontSize.stringToCGFloat()) {
  1893. annotationModel?.setFontName(newFont.fontName)
  1894. annotationModel?.setFontSize(newFont.pointSize)
  1895. }
  1896. }
  1897. }
  1898. }
  1899. }
  1900. updateAnnotation()
  1901. }
  1902. @IBAction func buttonClicked_SwitchIncludeTime(_ sender: NSButton) {
  1903. for case let tAnnotation as KMSelfSignAnnotationFreeText in annotations {
  1904. tAnnotation.includeTime = sender.state == .on ? true : false
  1905. let index = datePopUpButton.indexOfSelectedItem
  1906. datePopUpButton.removeAllItems()
  1907. datePopUpButton.addItems(withTitles: KMSelfSignAnnotationFreeText.fetchAllDateString(includeTime: false))
  1908. datePopUpButton.selectItem(at: index)
  1909. if self.subType == .date && isannotationMode {
  1910. UserDefaults.standard.set(sender.state == .on ? true : false, forKey: SKAnnotationSelfSignDateFormatterIncludeTimeKey)
  1911. }
  1912. }
  1913. reloadData()
  1914. }
  1915. @IBAction func dateCheckButtonAction(_ sender: NSPopUpButton) {
  1916. for case let tAnnotation as KMSelfSignAnnotationFreeText in annotations {
  1917. if subType == .date && isannotationMode {
  1918. let fetchArray = KMSelfSignAnnotationFreeText.fetchAllDateString(includeTime: false)
  1919. if sender.indexOfSelectedItem >= 0 && sender.indexOfSelectedItem <= fetchArray.count - 1 {
  1920. UserDefaults.standard.set(sender.indexOfSelectedItem, forKey: SKAnnotationSelfSignDateFormatterKey)
  1921. }
  1922. }
  1923. tAnnotation.dateFormatIndex = sender.indexOfSelectedItem
  1924. }
  1925. reloadData()
  1926. }
  1927. func annotationFontReload() {
  1928. DispatchQueue.global(qos: .default).async { [self] in
  1929. let fonts = NSFontManager.shared.availableFontFamilies
  1930. let menu = NSMenu()
  1931. var selectedIndex = 0
  1932. for (index, fontName) in fonts.enumerated() {
  1933. if let font = NSFont(name: fontName, size: 12.0) {
  1934. let attributedString = NSAttributedString(string: fontName, attributes: [NSAttributedString.Key.font: font])
  1935. let item = NSMenuItem()
  1936. item.attributedTitle = attributedString
  1937. menu.addItem(item)
  1938. if annotationType == .freeText {
  1939. if annotationModel?.fontName() == font.fontName {
  1940. selectedIndex = index
  1941. }
  1942. }
  1943. }
  1944. }
  1945. if annotationType == .freeText {
  1946. let freetextFont = NSFont(name: (annotationModel?.fontName() as? String)!, size: 16) ?? NSFont.systemFont(ofSize: 16)
  1947. if let family = freetextFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String,
  1948. let style = freetextFont.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.face) as? String {
  1949. DispatchQueue.main.async { [self] in
  1950. fontPopUpButton.menu = menu
  1951. fontPopUpButton.selectItem(at: selectedIndex)
  1952. let selectedStyleIndex = setFontStyle(fontName: family, currentStyle: style)
  1953. fontStylePopUpButton.selectItem(at: Int(selectedStyleIndex))
  1954. }
  1955. }
  1956. }
  1957. }
  1958. }
  1959. func adjustFreeText() {
  1960. if annotationModel?.annotations != nil {
  1961. if annotationType == .freeText || annotationType == .signText || annotationType == .signDate {
  1962. for an in (annotationModel?.annotations)! {
  1963. if let freeTextAn = an as? CPDFFreeTextAnnotation {
  1964. let font = freeTextAn.font
  1965. var attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font as Any]
  1966. let style = NSMutableParagraphStyle()
  1967. style.alignment = freeTextAn.alignment
  1968. attributes[NSAttributedString.Key.paragraphStyle] = style
  1969. let contents = freeTextAn.contents ?? ""
  1970. let textViewSize = contents.boundingRect(with: CGSize(width: freeTextAn.bounds.size.width, height: CGFloat(MAXFLOAT)),
  1971. options: .usesLineFragmentOrigin,
  1972. attributes: attributes).size
  1973. var rect = freeTextAn.bounds
  1974. if textViewSize.height != freeTextAn.bounds.size.height {
  1975. rect.origin.y -= (textViewSize.height - rect.size.height)
  1976. rect.size.height = textViewSize.height
  1977. }
  1978. if textViewSize.width < freeTextAn.bounds.size.width {
  1979. rect.size.width = textViewSize.width
  1980. }
  1981. freeTextAn.bounds = rect
  1982. }
  1983. }
  1984. }
  1985. }
  1986. }
  1987. // MARK: NSNotification
  1988. @objc func textDidChange(_ notification: Notification) {
  1989. // self.isTextEdit = true
  1990. //
  1991. // if self.subType == KMSelfSignAnnotationFreeTextSubType.freeText && isannotationMode {
  1992. // if let obj = notification.object as? NSObject {
  1993. // for tAnnotation in annotations {
  1994. // tAnnotation.setString(noteTextView.string)
  1995. // }
  1996. //
  1997. // if obj.isEqual(to: noteTextView) {
  1998. // UserDefaults.standard.set(noteTextView.string, forKey: SKAnnotationSelfSignPlaceHolderStringKey)
  1999. // }
  2000. //
  2001. // if annotation.isKind(of: CPDFFreeTextAnnotation.self) {
  2002. // textAnnotationImageView.image = annotationModel?.annotationImage
  2003. // } else {
  2004. // generalImageView.image = annotationModel?.annotationImage
  2005. // }
  2006. // }
  2007. // } else {
  2008. // if let obj = notification.object as? NSObject, obj.isEqual(to: noteTextView) {
  2009. // for tAnnotation in self.annotations {
  2010. // tAnnotation.setString(noteTextView.string)
  2011. // }
  2012. // }
  2013. // }
  2014. }
  2015. @objc func textDidEndEditing(_ notification: Notification) {
  2016. self.isTextEdit = true
  2017. if self.subType == KMSelfSignAnnotationFreeTextSubType.freeText && isannotationMode {
  2018. if let obj = notification.object as? NSObject {
  2019. for tAnnotation in annotations {
  2020. tAnnotation.setString(noteTextView.string)
  2021. }
  2022. if obj.isEqual(to: noteTextView) {
  2023. UserDefaults.standard.set(noteTextView.string, forKey: SKAnnotationSelfSignPlaceHolderStringKey)
  2024. }
  2025. if annotation.isKind(of: CPDFFreeTextAnnotation.self) {
  2026. textAnnotationImageView.image = annotationModel?.annotationImage
  2027. } else {
  2028. generalImageView.image = annotationModel?.annotationImage
  2029. }
  2030. }
  2031. } else {
  2032. if let obj = notification.object as? NSObject, obj.isEqual(to: noteTextView) {
  2033. for tAnnotation in self.annotations {
  2034. tAnnotation.setString(noteTextView.string)
  2035. }
  2036. }
  2037. }
  2038. }
  2039. @objc func themeChanged(_ notification: Notification) {
  2040. DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [self] in
  2041. updateViewColor()
  2042. }
  2043. }
  2044. }
  2045. class KMGeneralAnnotationColorButton: NSButton {
  2046. var _circleColor: NSColor = .clear
  2047. var _buttonBorderColor: NSColor = .clear
  2048. // MARK: Get & Set
  2049. var circleColor: NSColor {
  2050. set {
  2051. _circleColor = newValue
  2052. needsDisplay = true
  2053. }
  2054. get {
  2055. return _circleColor
  2056. }
  2057. }
  2058. var buttonBorderColor: NSColor {
  2059. set {
  2060. _buttonBorderColor = newValue
  2061. needsDisplay = true
  2062. }
  2063. get {
  2064. return _buttonBorderColor
  2065. }
  2066. }
  2067. // MARK: Init
  2068. required init?(coder: NSCoder) {
  2069. super.init(coder: coder)
  2070. wantsLayer = true
  2071. layer?.cornerRadius = 12.0
  2072. layer?.masksToBounds = true
  2073. layer?.borderColor = NSColor.clear.cgColor
  2074. }
  2075. override func draw(_ dirtyRect: NSRect) {
  2076. super.draw(dirtyRect)
  2077. let path3 = NSBezierPath(ovalIn: NSMakeRect(3, 3, dirtyRect.size.width - 6, dirtyRect.size.height - 6))
  2078. }
  2079. }
  2080. class KMNoteIconButtonCell: NSButtonCell {
  2081. override func drawImage(_ image: NSImage, withFrame frame: NSRect, in controlView: NSView) {
  2082. let titleSize = self.attributedTitle.size()
  2083. let imageSize = self.image!.size
  2084. var rect = NSZeroRect
  2085. let leftGap = (controlView.bounds.size.width - image.size.width) / 2.0
  2086. rect.origin.x = leftGap
  2087. if self.imagePosition == .imageAbove {
  2088. rect.origin.y = 6
  2089. } else {
  2090. rect.origin.y = (controlView.frame.size.height - image.size.height) / 2.0
  2091. }
  2092. rect.size = imageSize
  2093. super.drawImage(self.image!, withFrame: rect, in: controlView)
  2094. }
  2095. override func drawTitle(_ title: NSAttributedString, withFrame frame: NSRect, in controlView: NSView) -> NSRect {
  2096. let titleSize = self.attributedTitle.size()
  2097. let imageSize = self.image!.size
  2098. let totalHeight = titleSize.height + imageSize.height + 1
  2099. var rect = NSZeroRect
  2100. rect.origin.x = (controlView.bounds.size.width - titleSize.width) / 2.0
  2101. rect.origin.y = (controlView.bounds.size.height - totalHeight) / 2.0 + imageSize.height + 1
  2102. rect.size = titleSize
  2103. return super.drawTitle(title, withFrame: rect, in: controlView)
  2104. }
  2105. }